@ijfw/install 1.4.4 → 1.5.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/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 14 AI coding agents: Claude Code, Codex, Gemini, Cursor, Windsurf, Copilot, Hermes, Wayland, OpenCode, Qwen Code, Cline, Kimi Code, OpenClaw, and Aider.
4
+ efficiency layer for 15 AI coding agents: Claude Code, Codex, Gemini, Cursor, Windsurf, Copilot, Hermes, Wayland, OpenCode, Qwen Code, Cline, Kimi Code, OpenClaw, Antigravity, and Aider.
5
5
 
6
6
  ## Install
7
7
 
package/dist/ijfw.js CHANGED
@@ -1583,7 +1583,7 @@ var init_project_type_detector = __esm({
1583
1583
  });
1584
1584
 
1585
1585
  // ../mcp-server/src/gate-result.js
1586
- import { mkdir, writeFile } from "node:fs/promises";
1586
+ import { mkdir, writeFile, readdir, stat, unlink, appendFile } from "node:fs/promises";
1587
1587
  import { basename, dirname as dirname2, join as join6 } from "node:path";
1588
1588
  async function emitGateResult(gateOpts, context = {}) {
1589
1589
  if (gateOpts === null || typeof gateOpts !== "object") {
@@ -1643,6 +1643,7 @@ async function makeReceipt(gateResult, opts = {}) {
1643
1643
  await mkdir(dirname2(receiptPath), { recursive: true });
1644
1644
  const body = JSON.stringify(gateResult, null, 2) + "\n";
1645
1645
  await writeFile(receiptPath, body, "utf8");
1646
+ await evictOldReceipts(dirname2(receiptPath));
1646
1647
  } catch (err) {
1647
1648
  const msg = err && err.message ? err.message : String(err);
1648
1649
  try {
@@ -1652,6 +1653,58 @@ async function makeReceipt(gateResult, opts = {}) {
1652
1653
  }
1653
1654
  }
1654
1655
  }
1656
+ async function evictOldReceipts(dir, opts = {}) {
1657
+ const keep = Number.isFinite(opts.keep) && opts.keep > 0 ? opts.keep | 0 : RECEIPTS_KEEP;
1658
+ try {
1659
+ let entries;
1660
+ try {
1661
+ entries = await readdir(dir);
1662
+ } catch {
1663
+ return { evicted: 0 };
1664
+ }
1665
+ const jsonFiles = entries.filter((f) => f.endsWith(".json"));
1666
+ if (jsonFiles.length <= keep) return { evicted: 0 };
1667
+ const stamped = [];
1668
+ for (const f of jsonFiles) {
1669
+ const full = join6(dir, f);
1670
+ try {
1671
+ const s = await stat(full);
1672
+ stamped.push({ full, name: f, mtimeMs: s.mtimeMs });
1673
+ } catch {
1674
+ stamped.push({ full, name: f, mtimeMs: 0 });
1675
+ }
1676
+ }
1677
+ stamped.sort((a, b2) => b2.mtimeMs - a.mtimeMs);
1678
+ const toEvict = stamped.slice(keep);
1679
+ if (toEvict.length === 0) return { evicted: 0 };
1680
+ const archivePath = join6(dir, RECEIPTS_ARCHIVE);
1681
+ let evicted = 0;
1682
+ for (const victim of toEvict) {
1683
+ try {
1684
+ let body;
1685
+ try {
1686
+ const { readFile } = await import("node:fs/promises");
1687
+ body = await readFile(victim.full, "utf8");
1688
+ } catch {
1689
+ continue;
1690
+ }
1691
+ let archiveLine;
1692
+ try {
1693
+ archiveLine = JSON.stringify(JSON.parse(body)) + "\n";
1694
+ } catch {
1695
+ archiveLine = JSON.stringify({ raw: body, evicted_from: victim.name }) + "\n";
1696
+ }
1697
+ await appendFile(archivePath, archiveLine, "utf8");
1698
+ await unlink(victim.full);
1699
+ evicted++;
1700
+ } catch {
1701
+ }
1702
+ }
1703
+ return { evicted };
1704
+ } catch {
1705
+ return { evicted: 0 };
1706
+ }
1707
+ }
1655
1708
  async function resolveProjectType(projectRoot) {
1656
1709
  try {
1657
1710
  const root = typeof projectRoot === "string" && projectRoot.length > 0 ? projectRoot : process.cwd();
@@ -1667,12 +1720,14 @@ async function resolveProjectType(projectRoot) {
1667
1720
  return "unknown";
1668
1721
  }
1669
1722
  }
1670
- var RECEIPT_GATE_ID_PATTERN;
1723
+ var RECEIPT_GATE_ID_PATTERN, RECEIPTS_KEEP, RECEIPTS_ARCHIVE;
1671
1724
  var init_gate_result = __esm({
1672
1725
  "../mcp-server/src/gate-result.js"() {
1673
1726
  init_gate_result_schema();
1674
1727
  init_project_type_detector();
1675
1728
  RECEIPT_GATE_ID_PATTERN = /^[a-z][a-z0-9-]+$/;
1729
+ RECEIPTS_KEEP = 1e3;
1730
+ RECEIPTS_ARCHIVE = ".archive.jsonl";
1676
1731
  }
1677
1732
  });
1678
1733
 
@@ -1903,10 +1958,14 @@ import { tmpdir as tmpdir2 } from "node:os";
1903
1958
  async function run10(ctx) {
1904
1959
  const t0 = Date.now();
1905
1960
  const installerDir = join9(ctx.repoRoot, "installer");
1961
+ const cleanEnv = Object.fromEntries(
1962
+ Object.entries(process.env).filter(([k2]) => !k2.startsWith("npm_"))
1963
+ );
1906
1964
  const build = spawnSync10("npm", ["run", "build"], {
1907
1965
  encoding: "utf8",
1908
1966
  cwd: installerDir,
1909
1967
  timeout: 6e4,
1968
+ env: cleanEnv,
1910
1969
  shell: process.platform === "win32"
1911
1970
  });
1912
1971
  if (build.status !== 0) {
@@ -1918,10 +1977,12 @@ async function run10(ctx) {
1918
1977
  durationMs: Date.now() - t0
1919
1978
  };
1920
1979
  }
1921
- const pack = spawnSync10("npm", ["pack", "--silent"], {
1980
+ const packDir = mkdtempSync2(join9(tmpdir2(), "ijfw-packsmoke-tgz-"));
1981
+ const pack = spawnSync10("npm", ["pack", "--silent", "--pack-destination", packDir], {
1922
1982
  encoding: "utf8",
1923
1983
  cwd: installerDir,
1924
1984
  timeout: 3e4,
1985
+ env: cleanEnv,
1925
1986
  shell: process.platform === "win32"
1926
1987
  });
1927
1988
  if (pack.status !== 0) {
@@ -1943,7 +2004,7 @@ async function run10(ctx) {
1943
2004
  durationMs: Date.now() - t0
1944
2005
  };
1945
2006
  }
1946
- const tarballPath = resolve(installerDir, tarball);
2007
+ const tarballPath = resolve(packDir, tarball);
1947
2008
  const tmpRoot = mkdtempSync2(join9(tmpdir2(), "ijfw-pack-smoke-"));
1948
2009
  const fakeHome = join9(tmpRoot, "home");
1949
2010
  const installDir = join9(tmpRoot, "install");
@@ -1955,7 +2016,7 @@ async function run10(ctx) {
1955
2016
  encoding: "utf8",
1956
2017
  cwd: installDir,
1957
2018
  timeout: 6e4,
1958
- env: { ...process.env, HOME: fakeHome, npm_config_prefix: fakeHome },
2019
+ env: { ...cleanEnv, HOME: fakeHome, npm_config_prefix: fakeHome },
1959
2020
  shell: process.platform === "win32"
1960
2021
  });
1961
2022
  if (install.status !== 0) {
@@ -2026,7 +2087,7 @@ async function run10(ctx) {
2026
2087
  } catch {
2027
2088
  }
2028
2089
  try {
2029
- rmSync2(tarballPath, { force: true });
2090
+ rmSync2(packDir, { recursive: true, force: true });
2030
2091
  } catch {
2031
2092
  }
2032
2093
  }
@@ -2055,10 +2116,14 @@ import { tmpdir as tmpdir3 } from "node:os";
2055
2116
  async function run11(ctx) {
2056
2117
  const t0 = Date.now();
2057
2118
  const installerDir = join10(ctx.repoRoot, "installer");
2119
+ const cleanEnv = Object.fromEntries(
2120
+ Object.entries(process.env).filter(([k2]) => !k2.startsWith("npm_"))
2121
+ );
2058
2122
  const build = spawnSync11("npm", ["run", "build"], {
2059
2123
  encoding: "utf8",
2060
2124
  cwd: installerDir,
2061
2125
  timeout: 6e4,
2126
+ env: cleanEnv,
2062
2127
  shell: process.platform === "win32"
2063
2128
  });
2064
2129
  if (build.status !== 0) {
@@ -2070,10 +2135,12 @@ async function run11(ctx) {
2070
2135
  durationMs: Date.now() - t0
2071
2136
  };
2072
2137
  }
2073
- const pack = spawnSync11("npm", ["pack", "--silent"], {
2138
+ const packDir = mkdtempSync3(join10(tmpdir3(), "ijfw-upgradesmoke-tgz-"));
2139
+ const pack = spawnSync11("npm", ["pack", "--silent", "--pack-destination", packDir], {
2074
2140
  encoding: "utf8",
2075
2141
  cwd: installerDir,
2076
2142
  timeout: 3e4,
2143
+ env: cleanEnv,
2077
2144
  shell: process.platform === "win32"
2078
2145
  });
2079
2146
  if (pack.status !== 0) {
@@ -2086,7 +2153,7 @@ async function run11(ctx) {
2086
2153
  };
2087
2154
  }
2088
2155
  const tarball = pack.stdout.trim();
2089
- const tarballPath = resolve2(installerDir, tarball);
2156
+ const tarballPath = resolve2(packDir, tarball);
2090
2157
  const tmpRoot = mkdtempSync3(join10(tmpdir3(), "ijfw-upgrade-smoke-"));
2091
2158
  const fakeHome = join10(tmpRoot, "home");
2092
2159
  const installDir = join10(tmpRoot, "install");
@@ -2100,7 +2167,7 @@ async function run11(ctx) {
2100
2167
  encoding: "utf8",
2101
2168
  cwd: installDir,
2102
2169
  timeout: 6e4,
2103
- env: { ...process.env, HOME: fakeHome, npm_config_prefix: fakeHome },
2170
+ env: { ...cleanEnv, HOME: fakeHome, npm_config_prefix: fakeHome },
2104
2171
  shell: process.platform === "win32"
2105
2172
  });
2106
2173
  if (install.status !== 0) {
@@ -2195,7 +2262,7 @@ async function run11(ctx) {
2195
2262
  } catch {
2196
2263
  }
2197
2264
  try {
2198
- rmSync3(tarballPath, { force: true });
2265
+ rmSync3(packDir, { recursive: true, force: true });
2199
2266
  } catch {
2200
2267
  }
2201
2268
  }
@@ -3600,6 +3667,458 @@ import { fileURLToPath as fileURLToPath3 } from "node:url";
3600
3667
  import { existsSync as existsSync6, mkdirSync as mkdirSync5, copyFileSync as copyFileSync3, readdirSync as readdirSync5, rmSync as rmSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "node:fs";
3601
3668
  import { homedir, platform } from "node:os";
3602
3669
  import { spawnSync as spawnSync12 } from "node:child_process";
3670
+
3671
+ // src/command-registry.js
3672
+ var COMMAND_REGISTRY = Object.freeze([
3673
+ // ---------- TIER 1: PRIMARY (shown in `ijfw --help`) ----------
3674
+ {
3675
+ name: "install",
3676
+ tier: "primary",
3677
+ owner: "installer-direct",
3678
+ description: "Install IJFW into your AI coding agents",
3679
+ aliases: [],
3680
+ since: "1.0.0",
3681
+ status: "active",
3682
+ helpGroup: "GET STARTED"
3683
+ },
3684
+ {
3685
+ name: "uninstall",
3686
+ tier: "primary",
3687
+ owner: "installer-direct",
3688
+ description: "Remove IJFW (alias: off)",
3689
+ aliases: ["off"],
3690
+ since: "1.0.0",
3691
+ status: "active",
3692
+ helpGroup: "GET STARTED"
3693
+ },
3694
+ {
3695
+ name: "doctor",
3696
+ tier: "primary",
3697
+ owner: "installer-direct",
3698
+ description: "Diagnose installation health",
3699
+ aliases: [],
3700
+ since: "1.0.0",
3701
+ status: "active",
3702
+ helpGroup: "GET STARTED"
3703
+ },
3704
+ {
3705
+ name: "update",
3706
+ tier: "primary",
3707
+ owner: "orchestrator",
3708
+ description: "Upgrade to the latest IJFW",
3709
+ aliases: [],
3710
+ since: "1.1.0",
3711
+ status: "active",
3712
+ helpGroup: "GET STARTED"
3713
+ },
3714
+ {
3715
+ name: "demo",
3716
+ tier: "primary",
3717
+ owner: "orchestrator",
3718
+ description: "30-second Trident tour against a sample file",
3719
+ aliases: [],
3720
+ since: "1.2.0",
3721
+ status: "active",
3722
+ helpGroup: "USE IT"
3723
+ },
3724
+ {
3725
+ name: "cross",
3726
+ tier: "primary",
3727
+ owner: "orchestrator",
3728
+ description: "Run Trident audit/research/critique on any file",
3729
+ aliases: ["cross-audit", "cross-critique", "cross-research"],
3730
+ since: "1.2.0",
3731
+ status: "active",
3732
+ helpGroup: "USE IT"
3733
+ },
3734
+ {
3735
+ name: "dashboard",
3736
+ tier: "primary",
3737
+ owner: "installer-direct",
3738
+ description: "Start the local observability dashboard",
3739
+ aliases: [],
3740
+ since: "1.1.0",
3741
+ status: "active",
3742
+ helpGroup: "USE IT"
3743
+ },
3744
+ {
3745
+ name: "preflight",
3746
+ tier: "primary",
3747
+ owner: "installer-direct",
3748
+ description: "Run 11-gate quality pipeline before publishing",
3749
+ aliases: [],
3750
+ since: "1.0.0",
3751
+ status: "active",
3752
+ helpGroup: "USE IT"
3753
+ },
3754
+ {
3755
+ name: "help",
3756
+ tier: "primary",
3757
+ owner: "installer-direct",
3758
+ description: "Open the full IJFW guide",
3759
+ aliases: [],
3760
+ since: "1.0.0",
3761
+ status: "active",
3762
+ helpGroup: "EXPLORE"
3763
+ },
3764
+ {
3765
+ name: "commands",
3766
+ tier: "primary",
3767
+ owner: "installer-direct",
3768
+ description: "Show every command (advanced + coordination)",
3769
+ aliases: [],
3770
+ since: "1.5.1",
3771
+ status: "active",
3772
+ helpGroup: "EXPLORE"
3773
+ },
3774
+ {
3775
+ name: "version",
3776
+ tier: "primary",
3777
+ owner: "orchestrator",
3778
+ description: "Show version",
3779
+ aliases: ["--version", "-v"],
3780
+ since: "1.0.0",
3781
+ status: "active",
3782
+ helpGroup: "EXPLORE"
3783
+ },
3784
+ // ---------- TIER 2: COORDINATION (shown in `ijfw commands`) ----------
3785
+ {
3786
+ name: "status",
3787
+ tier: "coordination",
3788
+ owner: "orchestrator",
3789
+ description: "Show recent cross-audit activity",
3790
+ aliases: [],
3791
+ since: "1.2.0",
3792
+ status: "active"
3793
+ },
3794
+ {
3795
+ name: "receipt",
3796
+ tier: "coordination",
3797
+ owner: "orchestrator",
3798
+ description: "Print a redacted, shareable block from the last Trident run",
3799
+ aliases: [],
3800
+ since: "1.2.0",
3801
+ status: "active"
3802
+ },
3803
+ {
3804
+ name: "recover",
3805
+ tier: "coordination",
3806
+ owner: "orchestrator",
3807
+ description: "Show the latest checkpoint and next recovery step",
3808
+ aliases: [],
3809
+ since: "1.4.0",
3810
+ status: "active"
3811
+ },
3812
+ {
3813
+ name: "team",
3814
+ tier: "coordination",
3815
+ owner: "orchestrator",
3816
+ description: "Assemble project agents, charter, and workflow manifest",
3817
+ aliases: [],
3818
+ since: "1.4.0",
3819
+ status: "active"
3820
+ },
3821
+ {
3822
+ name: "swarm",
3823
+ tier: "coordination",
3824
+ owner: "orchestrator",
3825
+ description: "Plan artifact-aware parallel work from the team manifest",
3826
+ aliases: [],
3827
+ since: "1.4.0",
3828
+ status: "active"
3829
+ },
3830
+ {
3831
+ name: "blackboard",
3832
+ tier: "coordination",
3833
+ owner: "orchestrator",
3834
+ description: "Coordinate project-local swarm state and artifact claims",
3835
+ aliases: [],
3836
+ since: "1.4.0",
3837
+ status: "active"
3838
+ },
3839
+ {
3840
+ name: "memory",
3841
+ tier: "coordination",
3842
+ owner: "orchestrator",
3843
+ description: "Memory checkpoint operations (currently: `memory checkpoint <label>`)",
3844
+ aliases: [],
3845
+ since: "1.3.0",
3846
+ status: "active",
3847
+ notes: 'Only `memory checkpoint <label>` subcommand is implemented today. Top-level `ijfw memory` prints help, not "Unknown command".'
3848
+ },
3849
+ {
3850
+ name: "import",
3851
+ tier: "coordination",
3852
+ owner: "orchestrator",
3853
+ description: "Pull memory in from another tool (claude-mem, rtk)",
3854
+ aliases: [],
3855
+ since: "1.4.0",
3856
+ status: "active"
3857
+ },
3858
+ {
3859
+ name: "design",
3860
+ tier: "coordination",
3861
+ owner: "installer-direct",
3862
+ description: "Live visual design companion + durable design intelligence",
3863
+ aliases: [],
3864
+ since: "1.3.0",
3865
+ status: "active"
3866
+ },
3867
+ // ---------- TIER 3: PLUMBING (hidden by default; surfaced in `ijfw commands`) ----------
3868
+ {
3869
+ name: "statusline",
3870
+ tier: "plumbing",
3871
+ owner: "orchestrator",
3872
+ description: "Manage the statusline integration",
3873
+ aliases: [],
3874
+ since: "1.2.0",
3875
+ status: "active"
3876
+ },
3877
+ {
3878
+ name: "config",
3879
+ tier: "plumbing",
3880
+ owner: "orchestrator",
3881
+ description: "Inspect or audit IJFW configuration",
3882
+ aliases: [],
3883
+ since: "1.2.0",
3884
+ status: "active"
3885
+ },
3886
+ {
3887
+ name: "codex",
3888
+ tier: "plumbing",
3889
+ owner: "orchestrator",
3890
+ description: "Codex-specific helpers (doctor, sync-agents)",
3891
+ aliases: [],
3892
+ since: "1.3.0",
3893
+ status: "active"
3894
+ },
3895
+ {
3896
+ name: "extension",
3897
+ tier: "plumbing",
3898
+ owner: "orchestrator",
3899
+ description: "Manage installed IJFW extensions",
3900
+ aliases: [],
3901
+ since: "1.4.0",
3902
+ status: "active"
3903
+ },
3904
+ {
3905
+ name: "override",
3906
+ tier: "plumbing",
3907
+ owner: "orchestrator",
3908
+ description: "Manage extension overrides",
3909
+ aliases: [],
3910
+ since: "1.4.0",
3911
+ status: "active"
3912
+ },
3913
+ {
3914
+ name: "insight",
3915
+ tier: "plumbing",
3916
+ owner: "orchestrator",
3917
+ description: "Inspect IJFW insights",
3918
+ aliases: [],
3919
+ since: "1.4.0",
3920
+ status: "active"
3921
+ },
3922
+ {
3923
+ name: "ui-review",
3924
+ tier: "plumbing",
3925
+ owner: "orchestrator",
3926
+ description: "Run the visual UI review pipeline against a spec",
3927
+ aliases: [],
3928
+ since: "1.5.0",
3929
+ status: "active"
3930
+ },
3931
+ {
3932
+ name: "--purge-receipts",
3933
+ tier: "plumbing",
3934
+ owner: "orchestrator",
3935
+ description: "Clear the cross-runs receipt log",
3936
+ aliases: [],
3937
+ since: "1.2.0",
3938
+ status: "active",
3939
+ notes: 'Flag-style command (leading "--"). Registered as a name so parity check picks it up; documented under plumbing.'
3940
+ },
3941
+ // ---------- DEPRECATED: pointer-stub aliases ----------
3942
+ // These commands print "use the <X> skill" guidance and exit.
3943
+ // They live behind cross-orchestrator-cli.js COMMAND_ALIAS_HELP (derived from these entries).
3944
+ // Decision: keep them as silent redirects -- they have shipped documentation
3945
+ // pointing at them, removal is a breaking change.
3946
+ // status='deprecated' so help blocks suppress them, but dispatch still handles them.
3947
+ {
3948
+ name: "workflow",
3949
+ tier: "pointer-stub",
3950
+ owner: "orchestrator",
3951
+ description: "Redirect to the ijfw-workflow skill",
3952
+ aliases: [],
3953
+ since: "1.4.0",
3954
+ status: "deprecated",
3955
+ deprecatedReason: "Use the ijfw-workflow skill in agents. Terminal helpers: ijfw team init, ijfw swarm plan, ijfw swarm prepare."
3956
+ },
3957
+ {
3958
+ name: "handoff",
3959
+ tier: "pointer-stub",
3960
+ owner: "orchestrator",
3961
+ description: "Redirect to the ijfw-handoff skill",
3962
+ aliases: [],
3963
+ since: "1.4.0",
3964
+ status: "deprecated",
3965
+ deprecatedReason: 'Use the ijfw-handoff skill in agents, or record swarm handoff text with: ijfw blackboard handoff --message "<summary>".'
3966
+ },
3967
+ {
3968
+ name: "compress",
3969
+ tier: "pointer-stub",
3970
+ owner: "orchestrator",
3971
+ description: "Redirect to the ijfw-compress skill",
3972
+ aliases: [],
3973
+ since: "1.4.0",
3974
+ status: "deprecated",
3975
+ deprecatedReason: "Use the ijfw-compress skill in agents. Terminal context compression is host-specific and should preserve exact paths, commands, versions, and decisions."
3976
+ },
3977
+ {
3978
+ name: "consolidate",
3979
+ tier: "pointer-stub",
3980
+ owner: "orchestrator",
3981
+ description: "Redirect to the ijfw-handoff or ijfw-memory-audit skill",
3982
+ aliases: [],
3983
+ since: "1.4.0",
3984
+ status: "deprecated",
3985
+ deprecatedReason: "Use the ijfw-handoff or ijfw-memory-audit skill to consolidate decisions into memory. For swarm state, run: ijfw memory checkpoint <label>."
3986
+ },
3987
+ {
3988
+ name: "ijfw-audit",
3989
+ tier: "pointer-stub",
3990
+ owner: "orchestrator",
3991
+ description: "Redirect to `ijfw preflight`",
3992
+ aliases: [],
3993
+ since: "1.4.0",
3994
+ status: "deprecated",
3995
+ deprecatedReason: "Run verification with: ijfw preflight. For multi-model review, run: ijfw cross audit <target>."
3996
+ },
3997
+ {
3998
+ name: "ijfw-execute",
3999
+ tier: "pointer-stub",
4000
+ owner: "orchestrator",
4001
+ description: "Redirect to ijfw-workflow skill + swarm helpers",
4002
+ aliases: [],
4003
+ since: "1.4.0",
4004
+ status: "deprecated",
4005
+ deprecatedReason: "Use ijfw-workflow in agents, then terminal helpers: ijfw team init, ijfw swarm plan, ijfw swarm prepare, ijfw swarm start <task-id>."
4006
+ },
4007
+ {
4008
+ name: "ijfw-help",
4009
+ tier: "pointer-stub",
4010
+ owner: "orchestrator",
4011
+ description: "Redirect to `ijfw help`",
4012
+ aliases: [],
4013
+ since: "1.4.0",
4014
+ status: "deprecated",
4015
+ deprecatedReason: "Run: ijfw help. Add --browser for the rendered local guide."
4016
+ },
4017
+ {
4018
+ name: "ijfw-plan",
4019
+ tier: "pointer-stub",
4020
+ owner: "orchestrator",
4021
+ description: "Redirect to ijfw-workflow planning skills",
4022
+ aliases: [],
4023
+ since: "1.4.0",
4024
+ status: "deprecated",
4025
+ deprecatedReason: "Use ijfw-workflow for planning. Terminal helpers: ijfw team init, ijfw swarm plan, ijfw swarm prepare --reviews."
4026
+ },
4027
+ {
4028
+ name: "ijfw-ship",
4029
+ tier: "pointer-stub",
4030
+ owner: "orchestrator",
4031
+ description: "Redirect to `ijfw preflight`",
4032
+ aliases: [],
4033
+ since: "1.4.0",
4034
+ status: "deprecated",
4035
+ deprecatedReason: "Run: ijfw preflight. Do not publish or tag until your release gate is explicitly cleared."
4036
+ },
4037
+ {
4038
+ name: "ijfw-verify",
4039
+ tier: "pointer-stub",
4040
+ owner: "orchestrator",
4041
+ description: "Redirect to `ijfw preflight`",
4042
+ aliases: [],
4043
+ since: "1.4.0",
4044
+ status: "deprecated",
4045
+ deprecatedReason: "Run: ijfw preflight. For focused review, run: ijfw cross audit <target>."
4046
+ },
4047
+ {
4048
+ name: "memory-audit",
4049
+ tier: "pointer-stub",
4050
+ owner: "orchestrator",
4051
+ description: "Redirect to the ijfw-memory-audit skill",
4052
+ aliases: [],
4053
+ since: "1.4.0",
4054
+ status: "deprecated",
4055
+ deprecatedReason: "Use the ijfw-memory-audit skill in agents. Terminal safety net: ijfw recover status and ijfw memory checkpoint <label>."
4056
+ },
4057
+ {
4058
+ name: "memory-consent",
4059
+ tier: "pointer-stub",
4060
+ owner: "orchestrator",
4061
+ description: "Redirect to memory checkpoint",
4062
+ aliases: [],
4063
+ since: "1.4.0",
4064
+ status: "deprecated",
4065
+ deprecatedReason: "Use IJFW memory tools only for explicit project memory. Terminal checkpoint: ijfw memory checkpoint <label>."
4066
+ },
4067
+ {
4068
+ name: "memory-why",
4069
+ tier: "pointer-stub",
4070
+ owner: "orchestrator",
4071
+ description: "Redirect to ijfw-recall / ijfw-memory-audit skills",
4072
+ aliases: [],
4073
+ since: "1.4.0",
4074
+ status: "deprecated",
4075
+ deprecatedReason: "Use ijfw-recall or ijfw-memory-audit in agents to inspect why memory exists. Terminal recovery state: ijfw recover latest."
4076
+ },
4077
+ {
4078
+ name: "metrics",
4079
+ tier: "pointer-stub",
4080
+ owner: "orchestrator",
4081
+ description: "Redirect to the dashboard (real subcommand: metrics --benchmark)",
4082
+ aliases: [],
4083
+ since: "1.4.0",
4084
+ status: "deprecated",
4085
+ deprecatedReason: "Open the dashboard with: ijfw dashboard start. Agent-side metrics are available through ijfw_metrics. Run the memory benchmark harness with: ijfw metrics --benchmark."
4086
+ },
4087
+ {
4088
+ name: "mode",
4089
+ tier: "pointer-stub",
4090
+ owner: "orchestrator",
4091
+ description: "Redirect to `ijfw config --audit`",
4092
+ aliases: [],
4093
+ since: "1.4.0",
4094
+ status: "deprecated",
4095
+ deprecatedReason: "Inspect configuration with: ijfw config --audit. Statusline mode helpers: ijfw statusline --status, --compose, or --disable."
4096
+ }
4097
+ ]);
4098
+ var ORCHESTRATOR_COMMAND_NAMES = Object.freeze(new Set(
4099
+ COMMAND_REGISTRY.filter((e) => e.owner === "orchestrator").flatMap((e) => [e.name, ...e.aliases || []])
4100
+ ));
4101
+ var INSTALLER_DIRECT_COMMAND_NAMES = Object.freeze(new Set(
4102
+ COMMAND_REGISTRY.filter((e) => e.owner === "installer-direct").flatMap((e) => [e.name, ...e.aliases || []])
4103
+ ));
4104
+ var ALL_COMMAND_NAMES = Object.freeze(new Set(
4105
+ COMMAND_REGISTRY.flatMap((e) => [e.name, ...e.aliases || []])
4106
+ ));
4107
+ function primaryCommands() {
4108
+ return COMMAND_REGISTRY.filter(
4109
+ (e) => e.tier === "primary" && e.status === "active"
4110
+ );
4111
+ }
4112
+ function commandsByTier() {
4113
+ const tiers = { primary: [], coordination: [], plumbing: [] };
4114
+ for (const e of COMMAND_REGISTRY) {
4115
+ if (e.status !== "active") continue;
4116
+ if (tiers[e.tier]) tiers[e.tier].push(e);
4117
+ }
4118
+ return tiers;
4119
+ }
4120
+
4121
+ // src/ijfw.js
3603
4122
  var __dirname2 = dirname4(fileURLToPath3(import.meta.url));
3604
4123
  function repoRoot() {
3605
4124
  let dir = __dirname2;
@@ -3629,69 +4148,38 @@ function openBrowser(url) {
3629
4148
  const r = platform() === "darwin" ? spawnSync12("open", [url], { stdio: "ignore" }) : platform() === "win32" ? spawnSync12("cmd", ["/c", "start", "", url], { stdio: "ignore", shell: false }) : spawnSync12("xdg-open", [url], { stdio: "ignore" });
3630
4149
  return r.status ?? 0;
3631
4150
  }
3632
- var ORCHESTRATOR_COMMANDS = /* @__PURE__ */ new Set([
3633
- "update",
3634
- "statusline",
3635
- "config",
3636
- "insight",
3637
- "blackboard",
3638
- "team",
3639
- "swarm",
3640
- "codex",
3641
- "recover",
3642
- "memory",
3643
- "cross",
3644
- "status",
3645
- "demo",
3646
- "import",
3647
- "receipt",
3648
- "--purge-receipts",
3649
- "workflow",
3650
- "handoff",
3651
- "compress",
3652
- "consolidate",
3653
- "cross-audit",
3654
- "cross-critique",
3655
- "cross-research",
3656
- "ijfw-audit",
3657
- "ijfw-execute",
3658
- "ijfw-help",
3659
- "ijfw-plan",
3660
- "ijfw-ship",
3661
- "ijfw-verify",
3662
- "memory-audit",
3663
- "memory-consent",
3664
- "memory-why",
3665
- "metrics",
3666
- "mode",
3667
- "override",
3668
- "extension"
3669
- ]);
3670
4151
  function printHelp2() {
3671
- console.log(`
3672
- ijfw -- the AI efficiency layer
3673
-
3674
- USAGE
3675
- ijfw <command> [options]
3676
-
3677
- COMMANDS
3678
- install Install IJFW into your AI coding agents
3679
- uninstall Remove IJFW from your AI coding agents
3680
- help Open the full IJFW guide (terminal, or --browser for rendered)
3681
- preflight Run 11-gate quality pipeline before publishing
3682
- dashboard Start / stop / check the local observability dashboard
3683
- design Manage live previews and durable design intelligence
3684
- blackboard Coordinate project-local swarm state and artifact claims
3685
- codex Check and sync Codex-native IJFW surfaces
3686
- team Assemble project agents, charter, and workflow manifest
3687
- swarm Plan, prepare, and track artifact-aware parallel work
3688
- recover Show latest checkpoint and next recovery step
3689
- cross Run Trident audit/research/critique, e.g. ijfw cross audit README.md
3690
- doctor Diagnose IJFW installation health
3691
-
3692
- --help, -h Show this help
3693
- --version Show version
3694
- `);
4152
+ const grouped = { "GET STARTED": [], "USE IT": [], "EXPLORE": [] };
4153
+ for (const e of primaryCommands()) {
4154
+ if (grouped[e.helpGroup]) grouped[e.helpGroup].push(e);
4155
+ }
4156
+ let out = "\nijfw -- the AI efficiency layer\n\nUSAGE\n ijfw <command> [options]\n";
4157
+ for (const [group, entries] of Object.entries(grouped)) {
4158
+ if (entries.length === 0) continue;
4159
+ out += `
4160
+ ${group}
4161
+ `;
4162
+ for (const e of entries) {
4163
+ const displayName = e.name === "version" ? "--version" : e.name;
4164
+ const padded = displayName.padEnd(11);
4165
+ const descMentionsAlias = /\(alias:/i.test(e.description);
4166
+ const aliasNote = e.aliases.length && e.name !== "version" && !descMentionsAlias ? ` (alias: ${e.aliases.join(", ")})` : "";
4167
+ out += ` ${padded} ${e.description}${aliasNote}
4168
+ `;
4169
+ }
4170
+ }
4171
+ console.log(out);
4172
+ }
4173
+ function printCommands() {
4174
+ const t = commandsByTier();
4175
+ let out = "\nijfw -- full command surface\n";
4176
+ out += "\nPRIMARY (shown in --help)\n";
4177
+ out += " " + t.primary.map((e) => e.name).join(" \xB7 ") + "\n";
4178
+ out += "\nCOORDINATION (agents drive these; humans inspect)\n";
4179
+ out += " " + t.coordination.map((e) => e.name).join(" \xB7 ") + "\n";
4180
+ out += "\nPLUMBING (most users never need these)\n";
4181
+ out += " " + t.plumbing.map((e) => e.name).join(" \xB7 ") + "\n";
4182
+ console.log(out);
3695
4183
  }
3696
4184
  function doctorCheck(cmd, args) {
3697
4185
  const r = spawnSync12(cmd, args, { encoding: "utf8" });
@@ -3719,6 +4207,10 @@ async function main() {
3719
4207
  printHelp2();
3720
4208
  process.exit(0);
3721
4209
  }
4210
+ if (sub === "commands") {
4211
+ printCommands();
4212
+ process.exit(0);
4213
+ }
3722
4214
  if (sub === "--version" || sub === "-v" || sub === "version") {
3723
4215
  const verbose = argv.slice(3).includes("--verbose");
3724
4216
  if (delegateToCli(argv.slice(2))) return;
@@ -3734,7 +4226,12 @@ async function main() {
3734
4226
  }
3735
4227
  process.exit(0);
3736
4228
  }
3737
- if (ORCHESTRATOR_COMMANDS.has(sub)) {
4229
+ if (sub === "off") {
4230
+ const uninstallBin = resolve4(__dirname2, "..", "dist", "uninstall.js");
4231
+ const r = spawnSync12("node", [uninstallBin, ...argv.slice(3)], { stdio: "inherit" });
4232
+ process.exit(r.status ?? 1);
4233
+ }
4234
+ if (ORCHESTRATOR_COMMAND_NAMES.has(sub)) {
3738
4235
  if (delegateToCli(argv.slice(2))) return;
3739
4236
  console.error(`'ijfw ${sub}' requires a completed IJFW install. Run: ijfw install`);
3740
4237
  process.exit(1);
package/dist/install.js CHANGED
@@ -204,6 +204,8 @@ function isLive(targetId, home) {
204
204
  return hasBin("openclaw") || existsSync3(join3(H, ".openclaw"));
205
205
  case "aider":
206
206
  return hasBin("aider") || existsSync3(join3(H, ".aider.conf.yml"));
207
+ case "antigravity":
208
+ return hasBin("antigravity") || hasBin("agy") || existsSync3(join3(H, ".local", "bin", "agy")) || existsSync3(join3(H, ".gemini", "antigravity")) || existsSync3("/Applications/Antigravity.app");
207
209
  default:
208
210
  return false;
209
211
  }
@@ -223,14 +225,16 @@ function prettyName(targetId) {
223
225
  cline: "Cline",
224
226
  kimi: "Kimi Code",
225
227
  openclaw: "OpenClaw",
226
- aider: "Aider"
228
+ aider: "Aider",
229
+ antigravity: "Antigravity"
227
230
  };
228
231
  return map[targetId] || String(targetId);
229
232
  }
230
233
  function readJsonOrEmpty(path3) {
231
234
  if (!existsSync3(path3)) return {};
232
235
  try {
233
- const raw = readFileSync2(path3, "utf8") || "{}";
236
+ const raw = readFileSync2(path3, "utf8");
237
+ if (!raw || raw.trim() === "") return {};
234
238
  const parsed = JSON.parse(raw);
235
239
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
236
240
  return parsed;
@@ -1206,6 +1210,22 @@ function installAider(ctx) {
1206
1210
  printOk("Aider: rules-only install (~/.aider.conf.yml + ~/CONVENTIONS.md). No MCP -- Aider lacks a native MCP client.");
1207
1211
  return { status: "ok" };
1208
1212
  }
1213
+ function installAntigravity(ctx) {
1214
+ if (ctx.ijfwCustomDir || ctx.isIjfwSource) {
1215
+ printInfo("Skipping Antigravity platform writes (custom-dir or IJFW source tree).");
1216
+ printOk("Antigravity: real platform config left untouched.");
1217
+ return { status: "noop" };
1218
+ }
1219
+ const serverJs = ctx.serverJsNative || ctx.serverJs;
1220
+ const ideDst = path.join(ctx.home, ".gemini", "antigravity", "mcp_config.json");
1221
+ ensureDir2(path.dirname(ideDst));
1222
+ mergeJson(ideDst, serverJs);
1223
+ const cliDst = path.join(ctx.home, ".gemini", "config", "mcp_config.json");
1224
+ ensureDir2(path.dirname(cliDst));
1225
+ mergeJson(cliDst, serverJs);
1226
+ printOk(`Merged MCP into ${ideDst} + ${cliDst} (Antigravity IDE + CLI)`);
1227
+ return { status: "ok" };
1228
+ }
1209
1229
  var init_install_targets_8_14 = __esm({
1210
1230
  "src/install-targets-8-14.js"() {
1211
1231
  init_install_helpers();
@@ -1811,7 +1831,8 @@ var init_install_flow = __esm({
1811
1831
  "cline",
1812
1832
  "kimi",
1813
1833
  "openclaw",
1814
- "aider"
1834
+ "aider",
1835
+ "antigravity"
1815
1836
  ];
1816
1837
  TARGET_FNS = {
1817
1838
  claude: installClaude,
@@ -1827,7 +1848,8 @@ var init_install_flow = __esm({
1827
1848
  cline: installCline,
1828
1849
  kimi: installKimi,
1829
1850
  openclaw: installOpenclaw,
1830
- aider: installAider
1851
+ aider: installAider,
1852
+ antigravity: installAntigravity
1831
1853
  };
1832
1854
  install_flow_default = { runInstall, CANONICAL_ORDER };
1833
1855
  }
@@ -2211,7 +2233,7 @@ async function main() {
2211
2233
  } catch {
2212
2234
  }
2213
2235
  console.log("");
2214
- console.log("IJFW now active across 14 platforms -- one memory layer, all your models, zero config.");
2236
+ console.log("IJFW now active across 15 platforms -- one memory layer, all your models, zero config.");
2215
2237
  console.log(" Run `ijfw demo` to see the Trident in action.");
2216
2238
  console.log(" Run `ijfw doctor` to confirm which auditors are reachable.");
2217
2239
  console.log(" Privacy: everything stays local. See NO_TELEMETRY.md.");
package/dist/uninstall.js CHANGED
@@ -109,12 +109,13 @@ function writeAtomic(target, content) {
109
109
  }
110
110
  }
111
111
  function parseArgs(argv) {
112
- const out = { dir: null, purge: false, noMarketplace: false };
112
+ const out = { dir: null, purge: false, noMarketplace: false, yes: false };
113
113
  for (let i = 2; i < argv.length; i++) {
114
114
  const a = argv[i];
115
115
  if (a === "--dir") out.dir = argv[++i];
116
116
  else if (a === "--purge") out.purge = true;
117
117
  else if (a === "--no-marketplace") out.noMarketplace = true;
118
+ else if (a === "--yes" || a === "-y") out.yes = true;
118
119
  else if (a === "--help" || a === "-h") {
119
120
  printHelp();
120
121
  process.exit(0);
@@ -124,11 +125,31 @@ function parseArgs(argv) {
124
125
  }
125
126
  function printHelp() {
126
127
  console.log(`ijfw-uninstall -- reverse IJFW install
127
- Usage: ijfw-uninstall [--dir <path>] [--purge] [--no-marketplace]
128
+ Usage: ijfw-uninstall [--dir <path>] [--purge] [--no-marketplace] [--yes]
128
129
  --purge also remove memory/ (destructive)
129
130
  --no-marketplace skip ~/.claude/settings.json edits
131
+ --yes, -y skip the confirmation prompt (for scripted use)
130
132
  `);
131
133
  }
134
+ function confirm(question) {
135
+ return new Promise((res) => {
136
+ process.stdout.write(question);
137
+ const onData = (chunk) => {
138
+ process.stdin.removeListener("data", onData);
139
+ try {
140
+ process.stdin.pause();
141
+ } catch {
142
+ }
143
+ const answer = String(chunk).trim().toLowerCase();
144
+ res(answer === "y" || answer === "yes");
145
+ };
146
+ try {
147
+ process.stdin.resume();
148
+ } catch {
149
+ }
150
+ process.stdin.once("data", onData);
151
+ });
152
+ }
132
153
  var HOME = homedir2();
133
154
  var TS = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").replace("T", "_").slice(0, 19);
134
155
  function backupFile(p) {
@@ -364,7 +385,18 @@ async function main() {
364
385
  const opts = parseArgs(process.argv);
365
386
  const target = resolveTarget(opts);
366
387
  console.log("This will remove IJFW configuration. Your memory at ~/.ijfw/memory/ will be preserved. Delete manually if desired.");
388
+ if (opts.purge) {
389
+ console.log("WARNING: --purge will also DELETE ~/.ijfw/memory/ (project memory cannot be recovered).");
390
+ }
367
391
  console.log("");
392
+ if (!opts.yes && process.stdin.isTTY) {
393
+ const ok = await confirm("Proceed with IJFW uninstall? [y/N] ");
394
+ if (!ok) {
395
+ console.log("Uninstall cancelled. Nothing was changed.");
396
+ process.exit(0);
397
+ }
398
+ console.log("");
399
+ }
368
400
  if (!existsSync2(target)) {
369
401
  console.log(`IJFW directory absent (${target}); platform cleanup only.`);
370
402
  } else if (opts.purge) {
package/docs/GUIDE.md CHANGED
@@ -1,9 +1,11 @@
1
1
  <p align="center">
2
- <img src="https://gitlab.com/therealseandonahoe/ijfw/releases/download/v1.1.1/ijfw-hero.png" alt="IJFW" width="100%"/>
2
+ <img src="guide/assets/hero.png" alt="IJFW" width="100%"/>
3
3
  </p>
4
4
 
5
5
  # The IJFW Guide
6
6
 
7
+ > **Note**: This guide is being rewritten for v1.5.x in milestone v1.5.1 W5. Some sections are out of date.
8
+
7
9
  **90 seconds to your first win. 10 minutes to the full tour. 45 minutes to master it.**
8
10
 
9
11
  This guide is bundled with every install. Run `ijfw help` in your terminal for the terminal-native version, or `ijfw help --browser` to read it in a rendered browser tab with images and syntax highlighting.
@@ -40,7 +42,7 @@ One command. Three seconds.
40
42
  npm install -g @ijfw/install && ijfw-install
41
43
  ```
42
44
 
43
- That installs the npm package, runs the installer, and wires up every AI coding agent it finds on your machine. Claude Code, Codex, Gemini, Cursor, Windsurf, and Copilot all pick up the shared memory and the same workflow discipline.
45
+ That installs the npm package, runs the installer, and wires up every AI coding agent it finds on your machine. All 15 supported platforms — Claude Code, Codex, Gemini, Cursor, Windsurf, Copilot, Hermes, Wayland, Antigravity, and the rest pick up the shared memory and the same workflow discipline.
44
46
 
45
47
  If you do not type commands, paste this block into Claude Code, Cursor, or any other AI coding agent. It will install IJFW for you, verify the MCP server handshake, and tell you when to restart.
46
48
 
@@ -82,16 +84,16 @@ In Claude Code, the same runs as `/cross-audit <file>` or simply "cross-audit th
82
84
 
83
85
  Tell IJFW a decision in one session. Ask for it in another. No configuration required.
84
86
 
85
- **Session A, any project:**
87
+ **Session A, any project:** ask your AI in plain language to remember a decision. In Claude Code, the `ijfw-auto-memorize` skill captures it. To force a snapshot from the shell:
86
88
 
87
89
  ```bash
88
- ijfw memory store "We pin all npm packages to exact versions, no carets, decided 2026-04-19 because dependabot churn was destabilizing CI."
90
+ ijfw memory checkpoint "We pin all npm packages to exact versions, no carets, decided 2026-04-19 because dependabot churn was destabilizing CI."
89
91
  ```
90
92
 
91
- **Session B, a completely different project, hours or days later:**
93
+ **Session B, a completely different project, hours or days later:** ask "what did we decide about version pinning?" The `ijfw-recall` skill (Claude Code) or the MCP `ijfw_memory_search` tool (any platform) surfaces it. To query from the shell:
92
94
 
93
95
  ```bash
94
- ijfw memory recall "version pinning"
96
+ ijfw memory search "version pinning"
95
97
  ```
96
98
 
97
99
  It comes back. Full quote, original date, original project. Your AI is no longer amnesiac.
@@ -142,7 +144,7 @@ Every IJFW command sits on top of one opinionated workflow: **Think, Build, Ship
142
144
 
143
145
  Every phase is conversational. One question at a time. No monologues. Every artifact summarizes in chat before it writes to disk. Every gate is a user-facing checklist, never a silent pass.
144
146
 
145
- To start: say "let's plan a new feature", "help me ship this", or "let's build X". In Claude Code the same triggers as `/workflow` or `/ijfw-plan`.
147
+ To start: say "let's plan a new feature", "help me ship this", or "let's build X". The `ijfw-workflow` skill auto-loads from the trigger phrase.
146
148
 
147
149
  ### The observability dashboard
148
150
 
@@ -172,9 +174,9 @@ Run `/team setup` in Claude Code, or `ijfw team` from the shell, to see your cur
172
174
  |------|-------|--------------|
173
175
  | Hot | Plain markdown in `.ijfw/memory/` | Always on. Instant reads. Git friendly. |
174
176
  | Warm | BM25 ranked search | Always on. Scales to around 10,000 entries per project. |
175
- | Cold | Optional semantic vectors | Off by default. Requires a user-installed embedding provider. |
177
+ | Cold | Optional semantic vectors (hybrid BM25 + cosine rerank) | Off by default. Enable with `IJFW_VECTORS=on` and `npm i @xenova/transformers` (one-time ~23MB MiniLM model cached locally). Top-K BM25 candidates are reranked via cosine similarity with weights 0.6 BM25 / 0.4 vector. Pure no-op fallback to BM25 if disabled, the package isn't installed, or the model fails to load. |
176
178
 
177
- Every session also ends with an optional "dream cycle". Run `/consolidate` or "run a dream cycle" to have IJFW sweep the day's memory: promote observed patterns into your knowledge base, prune stale entries, reconcile contradictions, optionally lift winners into global memory so every future project benefits. Memory that grows sharper over time instead of heavier.
179
+ Every session also ends with an optional "dream cycle". Say "run a dream cycle" or "consolidate memory" and the `ijfw-auto-memorize` skill sweeps the day's memory: promote observed patterns into your knowledge base, prune stale entries, reconcile contradictions, optionally lift winners into global memory so every future project benefits. Memory that grows sharper over time instead of heavier.
178
180
 
179
181
  ### Smart routing and the token economy
180
182
 
@@ -182,11 +184,7 @@ Inside Claude Code, tasks dispatch to the right model automatically. Reads go to
182
184
 
183
185
  Typical observed saving: 25 percent or more output reduction versus an unmanaged baseline (same task, same prompt, no IJFW rules or routing applied). Your mileage varies by task, model, and cache state. The savings print in every session receipt so you can audit every claim against your own logs.
184
186
 
185
- To see the running total with a breakdown by platform and session:
186
-
187
- ```bash
188
- ijfw metrics
189
- ```
187
+ To see the running total with a breakdown by platform and session, ask your AI for "session metrics" — the `ijfw_metrics` MCP tool surfaces tokens, cost, and routing mix from `.ijfw/metrics/sessions.jsonl`.
190
188
 
191
189
  ---
192
190
 
@@ -194,11 +192,11 @@ ijfw metrics
194
192
 
195
193
  By tomorrow your AI already feels different. Three small habits compound the effect.
196
194
 
197
- 1. **End every significant session with `ijfw handoff`.** It writes a short file other sessions can pick up from. New session, say "recall" or `/handoff`, and you are back in context instantly.
195
+ 1. **End every significant session by asking your AI to "write a handoff".** The `ijfw-handoff` skill writes a short file other sessions can pick up from. New session, say "recall last handoff" and you are back in context instantly.
198
196
 
199
197
  2. **Run `ijfw cross audit` before you merge anything meaningful.** Even if you are the only reviewer, the Trident is a second opinion that costs pennies and catches what single-model eyes miss. Most IJFW users wire it into their git post-commit hook after a week.
200
198
 
201
- 3. **Say "consolidate" once a week.** The dream cycle keeps memory sharp. Without it, memory grows heavier instead of smarter.
199
+ 3. **Ask your AI to "consolidate memory" once a week.** The dream cycle keeps memory sharp. Without it, memory grows heavier instead of smarter.
202
200
 
203
201
  Everything else in IJFW builds on those three habits. Part 2 below is the full reference if you want to see every command and every skill.
204
202
 
@@ -227,17 +225,14 @@ Every command ships in three forms: a shell command, a Claude Code slash command
227
225
  | `ijfw status` | Hero line plus recent activity plus cache savings. |
228
226
  | `ijfw doctor` | Probe every AI CLI and API key. Tells you what is live and what is standing by. |
229
227
  | `ijfw help` | Show this guide, paged. Add `--browser` to render in a browser tab. |
230
- | `ijfw handoff` | Save a context handoff for the next session. |
231
228
  | `ijfw receipt last` | Print the last Trident receipt, redacted and shareable. |
232
229
 
233
230
  ### Memory
234
231
 
235
232
  | Command | Purpose |
236
233
  |---------|---------|
237
- | `ijfw memory store "<text>"` | Persist a decision, pattern, or note. |
238
- | `ijfw memory recall "<query>"` | BM25 ranked search over local memory. |
239
- | `ijfw memory status` | Roughly 200-token project brief. Mode, pending, last handoff. |
240
- | `ijfw memory search --scope all "<query>"` | Search across every registered IJFW project on this machine. |
234
+ | `ijfw memory checkpoint "<text>"` | Snapshot a decision, pattern, or note to local memory. |
235
+ | `ijfw memory search "<query>"` | BM25 ranked search over local memory. Add `--scope all` to search every registered IJFW project. |
241
236
  | `ijfw import claude-mem` | Absorb existing claude-mem SQLite memory into IJFW markdown. |
242
237
  | `ijfw import claude-mem --all` | Discover projects automatically, import in bulk. |
243
238
  | `ijfw import claude-mem --dry-run` | Show what would happen first. |
@@ -258,7 +253,6 @@ Every command ships in three forms: a shell command, a Claude Code slash command
258
253
  | `ijfw dashboard start` | Bind `127.0.0.1:37891`, open the dashboard tab. |
259
254
  | `ijfw dashboard stop` | Graceful shutdown. |
260
255
  | `ijfw dashboard status` | Port plus observation count. |
261
- | `ijfw metrics` | Tokens, cost, routing mix, session totals. |
262
256
 
263
257
  ### Quality gates
264
258
 
@@ -320,7 +314,7 @@ Full list in Claude Code: run `/ijfw` or just type `ijfw` in conversation to see
320
314
 
321
315
  ## Workflow modes
322
316
 
323
- IJFW auto-picks from your prompt. You can also pick explicitly with `ijfw-plan quick` or `ijfw-plan deep`.
317
+ IJFW auto-picks from your prompt. You can also state your preference explicitly ("plan this in quick mode" or "use deep mode") and the `ijfw-workflow` skill will route accordingly.
324
318
 
325
319
  ### Quick mode (3 to 5 minutes)
326
320
 
@@ -355,17 +349,21 @@ Every module is a single question, answered in chat. Artifacts summarize in chat
355
349
 
356
350
  ## Platform parity
357
351
 
358
- IJFW configures six AI coding agents with native affordances on each, plus a universal rules file you can paste into anything else.
352
+ IJFW configures 15 AI coding agents with native affordances on each, plus a universal rules file you can paste into anything else. Every platform speaks the same MCP server (13 tools), the same memory tiers, and the same observation ledger.
359
353
 
360
354
  | Platform | What ships |
361
355
  |----------|------------|
362
- | Claude Code | Native plugin via marketplace, MCP auto-registered, 6 hook events / 12 scripts, 22 on-demand skills, 22 slash commands |
363
- | Codex CLI | Native plugin (`.codex-plugin/plugin.json`), 19 skills, 5 hook events, MCP registered, marketplace-ready |
364
- | Gemini CLI | Native extension (`gemini-extension.json`), 19 skills, 11 hook events, 19 TOML slash commands, policy engine, BeforeModel injection, checkpointing |
356
+ | Claude Code | Native plugin via marketplace, MCP auto-registered, full hook lifecycle, on-demand skills, slash commands |
357
+ | Codex CLI | Native plugin (`.codex-plugin/plugin.json`), skills, hook events, MCP registered, marketplace-ready |
358
+ | Gemini CLI | Native extension (`gemini-extension.json`), skills, hook events, TOML slash commands, policy engine, BeforeModel injection, checkpointing |
365
359
  | Cursor | `.cursor/mcp.json` plus `.cursor/rules/ijfw.mdc`. Dashboard view-only. |
366
360
  | Windsurf | `~/.codeium/windsurf/mcp_config.json` plus `.windsurfrules`. Dashboard view-only. |
367
361
  | Copilot (VS Code) | `.vscode/mcp.json` plus `.github/copilot-instructions.md`. Dashboard view-only. |
368
- | Universal | `universal/ijfw-rules.md`. Paste into anything else. |
362
+ | Hermes CLI | `HERMES.md` plus MCP registration in `~/.hermes/config.yaml`. |
363
+ | Wayland CLI | `WAYLAND.md` plus MCP registration in `~/.wayland/config.yaml`. |
364
+ | Antigravity | `~/.gemini/antigravity/mcp_config.json` (Google's VS Code-fork agentic IDE; Windsurf-identical MCP schema). Agent context via shared `AGENTS.md`. Dashboard view-only. |
365
+ | Additional MCP-aware agents | IJFW detects and configures the remaining supported agents via their native MCP and rules-file integrations to reach 15 total. |
366
+ | Universal | `universal/ijfw-rules.md`. 20-line paste-anywhere rules file for anything else. |
369
367
 
370
368
  ### Observation ledger parity
371
369
 
@@ -377,8 +375,9 @@ IJFW configures six AI coding agents with native affordances on each, plus a uni
377
375
  | Cursor | view-only | yes | none |
378
376
  | Windsurf | view-only | yes | none |
379
377
  | Copilot | view-only | yes | none |
378
+ | Hermes / Wayland / other MCP-aware agents | view-only | yes | none |
380
379
 
381
- Claude, Codex, and Gemini write one JSONL line per tool call. Cursor, Windsurf, and Copilot have no hook lifecycle IJFW can write from, so they read the shared ledger via the dashboard instead. Same engine behind all of them.
380
+ Claude, Codex, and Gemini write one JSONL line per tool call. The remaining platforms have no hook lifecycle IJFW can write from, so they read the shared ledger via the dashboard instead. Same engine behind all of them.
382
381
 
383
382
  ---
384
383
 
@@ -510,7 +509,7 @@ Every install writes a log to `~/.ijfw/install.log`. Every session writes observ
510
509
  ## FAQ
511
510
 
512
511
  **Is this just a Claude Code plugin?**
513
- No. Claude Code is one of six platforms. The plugin is richest there because Claude Code exposes the most integration points. Every capability is available on the other five through their native MCP and rules-file integrations.
512
+ No. Claude Code is one of 15 platforms. The plugin is richest there because Claude Code exposes the most integration points. Every capability is available on the other agents through their native MCP and rules-file integrations.
514
513
 
515
514
  **Do I need a specific AI provider?**
516
515
  No. IJFW configures the agents you already have. Bring your own keys, your own CLIs. The Trident uses whatever auditors are reachable on your machine. One is enough to start.
@@ -534,7 +533,7 @@ MCP handshake is about 50 ms. Hooks are under 30 ms. Memory recall across thousa
534
533
  `ijfw update` pulls latest and reinstalls merge-safely. Your memory is preserved.
535
534
 
536
535
  **Does it work on Windows?**
537
- Yes. Git Bash (bundled with Git for Windows) is the supported shell. A PowerShell entry point lives at `installer/src/install.ps1` for users who prefer native PowerShell.
536
+ Yes. The installer is Node-native end to end -- no bash, no WSL, no Git for Windows shell required. A PowerShell entry point lives at `installer/src/install.ps1`; if execution policy blocks it, run `powershell -ExecutionPolicy Bypass -File .\install.ps1`.
538
537
 
539
538
  **Can my team share memory?**
540
539
  Yes. `.ijfw/team/` is git-committed by default. Decisions, patterns, and stack conventions travel with the repo. A new hire's first session inherits all of it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ijfw/install",
3
- "version": "1.4.4",
3
+ "version": "1.5.1",
4
4
  "description": "One-command installer for IJFW -- the AI efficiency layer. One install, every AI coding agent, zero config.",
5
5
  "type": "module",
6
6
  "bin": {