@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 +1 -1
- package/dist/ijfw.js +570 -73
- package/dist/install.js +27 -5
- package/dist/uninstall.js +34 -2
- package/docs/GUIDE.md +30 -31
- package/package.json +1 -1
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
|
|
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
|
|
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(
|
|
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: { ...
|
|
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(
|
|
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
|
|
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(
|
|
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: { ...
|
|
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(
|
|
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
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
ijfw <command> [options]
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
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 (
|
|
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
|
|
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="
|
|
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
|
|
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
|
|
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
|
|
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".
|
|
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.
|
|
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".
|
|
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
|
|
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. **
|
|
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
|
|
238
|
-
| `ijfw 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
|
|
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
|
|
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,
|
|
363
|
-
| Codex CLI | Native plugin (`.codex-plugin/plugin.json`),
|
|
364
|
-
| Gemini CLI | Native extension (`gemini-extension.json`),
|
|
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
|
-
|
|
|
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.
|
|
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
|
|
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.
|
|
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.
|