@graphit/cli 0.1.107 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/bin/graphit +8 -1
- package/bin/graphit.ps1 +5 -1
- package/dist/commands/plugin.js +3 -0
- package/dist/commands/plugin.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/update-check.d.ts +1 -0
- package/dist/update-check.js +18 -1
- package/dist/update-check.js.map +1 -1
- package/package.json +1 -1
- package/scripts/plugin-status.mjs +293 -13
- package/skills/graphit/SKILL.md +3 -3
- package/skills/graphit/VERSION.json +1 -1
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"metadata": {
|
|
9
9
|
"description": "Graphit CLI plugin for AI coding assistants",
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.2.0"
|
|
11
11
|
},
|
|
12
12
|
"plugins": [
|
|
13
13
|
{
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
"source": {
|
|
17
17
|
"source": "npm",
|
|
18
18
|
"package": "@graphit/cli",
|
|
19
|
-
"version": "0.
|
|
19
|
+
"version": "0.2.0"
|
|
20
20
|
},
|
|
21
|
-
"version": "0.
|
|
21
|
+
"version": "0.2.0",
|
|
22
22
|
"category": "data-visualization",
|
|
23
23
|
"tags": [
|
|
24
24
|
"bi",
|
package/bin/graphit
CHANGED
|
@@ -6,8 +6,15 @@
|
|
|
6
6
|
# untrusted), and falls back to the stamped floor version when the cache is absent
|
|
7
7
|
# or invalid. The floor keeps first-run and offline working.
|
|
8
8
|
|
|
9
|
+
# Tell the npm CLI which plugin bundle launched it. Existing stale wrappers may
|
|
10
|
+
# not have this yet, so the CLI also inspects Claude's installed plugin registry.
|
|
11
|
+
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
12
|
+
if [ -z "${GRAPHIT_PLUGIN_ROOT:-}" ]; then
|
|
13
|
+
export GRAPHIT_PLUGIN_ROOT="$(cd "${script_dir}/.." && pwd -P)"
|
|
14
|
+
fi
|
|
15
|
+
|
|
9
16
|
# graphit:floor (stamped by scripts/sync-plugin-version.mjs from cli/package.json)
|
|
10
|
-
FLOOR_VERSION="0.
|
|
17
|
+
FLOOR_VERSION="0.2.0"
|
|
11
18
|
|
|
12
19
|
PACKAGE_NAME="@graphit/cli"
|
|
13
20
|
# Strict semver: anything else is rejected so a tampered cache cannot inject.
|
package/bin/graphit.ps1
CHANGED
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
# @graphit/cli via npx. Reads + validates the resolver cache (user-writable, so
|
|
3
3
|
# untrusted) and falls back to the stamped floor version when absent/invalid.
|
|
4
4
|
|
|
5
|
+
if (-not $env:GRAPHIT_PLUGIN_ROOT) {
|
|
6
|
+
$env:GRAPHIT_PLUGIN_ROOT = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
|
|
7
|
+
}
|
|
8
|
+
|
|
5
9
|
# graphit:floor (stamped by scripts/sync-plugin-version.mjs from cli/package.json)
|
|
6
|
-
$FloorVersion = "0.
|
|
10
|
+
$FloorVersion = "0.2.0"
|
|
7
11
|
|
|
8
12
|
$PackageName = "@graphit/cli"
|
|
9
13
|
# Strict semver: anything else is rejected so a tampered cache cannot inject.
|
package/dist/commands/plugin.js
CHANGED
|
@@ -16,6 +16,7 @@ export function registerPluginCommands(program) {
|
|
|
16
16
|
.option("--json", "Print structured JSON")
|
|
17
17
|
.option("--quiet", "Print only when action is needed")
|
|
18
18
|
.option("--skip-network", "Skip npm latest-version lookup")
|
|
19
|
+
.option("--repair", "Repair stale local Claude Code plugin cache when safe")
|
|
19
20
|
.action(function () {
|
|
20
21
|
const script = resolvePluginStatusScript();
|
|
21
22
|
if (!existsSync(script)) {
|
|
@@ -30,6 +31,8 @@ export function registerPluginCommands(program) {
|
|
|
30
31
|
args.push("--quiet");
|
|
31
32
|
if (opts.skipNetwork)
|
|
32
33
|
args.push("--skip-network");
|
|
34
|
+
if (opts.repair)
|
|
35
|
+
args.push("--repair");
|
|
33
36
|
const result = spawnSync(process.execPath, args, {
|
|
34
37
|
stdio: "inherit",
|
|
35
38
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/commands/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,SAAS,yBAAyB;IAChC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,mBAAmB,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,MAAM,GAAG,OAAO;SACnB,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,yCAAyC,CAAC,CAAC;IAE1D,MAAM;SACH,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,2CAA2C,CAAC;SACxD,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC;SACzC,MAAM,CAAC,SAAS,EAAE,kCAAkC,CAAC;SACrD,MAAM,CAAC,gBAAgB,EAAE,gCAAgC,CAAC;SAC1D,MAAM,CAAC;QACN,MAAM,MAAM,GAAG,yBAAyB,EAAE,CAAC;QAC3C,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,4DAA4D,EAAE,CAAC,CAAC,CAAC;YACvG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QACtB,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,IAAI,CAAC,WAAW;YAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/commands/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,SAAS,yBAAyB;IAChC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,mBAAmB,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,MAAM,GAAG,OAAO;SACnB,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,yCAAyC,CAAC,CAAC;IAE1D,MAAM;SACH,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,2CAA2C,CAAC;SACxD,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC;SACzC,MAAM,CAAC,SAAS,EAAE,kCAAkC,CAAC;SACrD,MAAM,CAAC,gBAAgB,EAAE,gCAAgC,CAAC;SAC1D,MAAM,CAAC,UAAU,EAAE,uDAAuD,CAAC;SAC3E,MAAM,CAAC;QACN,MAAM,MAAM,GAAG,yBAAyB,EAAE,CAAC;QAC3C,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,4DAA4D,EAAE,CAAC,CAAC,CAAC;YACvG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QACtB,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,IAAI,CAAC,WAAW;YAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAClD,IAAI,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAEvC,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE;YAC/C,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { registerSetupCommand } from "./commands/setup.js";
|
|
|
10
10
|
import { registerGovernanceCommands } from "./commands/governance.js";
|
|
11
11
|
import { registerTeamCommands } from "./commands/team.js";
|
|
12
12
|
import { registerPluginCommands } from "./commands/plugin.js";
|
|
13
|
-
import { getCurrentVersion, printUpdateBanner, printMigrationNoticeIfGlobal, fireBackgroundCheck, } from "./update-check.js";
|
|
13
|
+
import { getCurrentVersion, printUpdateBanner, printMigrationNoticeIfGlobal, printPluginHealthPreflight, fireBackgroundCheck, } from "./update-check.js";
|
|
14
14
|
const program = new Command();
|
|
15
15
|
const args = process.argv.slice(2);
|
|
16
16
|
const pluginArgIndex = args.indexOf("plugin");
|
|
@@ -34,6 +34,7 @@ registerSetupCommand(program);
|
|
|
34
34
|
if (!isPluginStatusCommand) {
|
|
35
35
|
printMigrationNoticeIfGlobal();
|
|
36
36
|
printUpdateBanner();
|
|
37
|
+
printPluginHealthPreflight();
|
|
37
38
|
}
|
|
38
39
|
program.parse();
|
|
39
40
|
fireBackgroundCheck();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,4BAA4B,EAC5B,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC9C,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC9C,MAAM,qBAAqB,GAAG,cAAc,IAAI,CAAC,IAAI,cAAc,KAAK,cAAc,GAAG,CAAC,CAAC;AAE3F,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,oEAAoE,CAAC;KACjF,OAAO,CAAC,iBAAiB,EAAE,CAAC;KAC5B,MAAM,CAAC,mBAAmB,EAAE,iDAAiD,EAAE,MAAM,CAAC,CAAC;AAE1F,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAC5B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAC5B,yBAAyB,CAAC,OAAO,CAAC,CAAC;AACnC,yBAAyB,CAAC,OAAO,CAAC,CAAC;AACnC,0BAA0B,CAAC,OAAO,CAAC,CAAC;AACpC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAE9B,IAAI,CAAC,qBAAqB,EAAE,CAAC;IAC3B,4BAA4B,EAAE,CAAC;IAC/B,iBAAiB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,4BAA4B,EAC5B,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC9C,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC9C,MAAM,qBAAqB,GAAG,cAAc,IAAI,CAAC,IAAI,cAAc,KAAK,cAAc,GAAG,CAAC,CAAC;AAE3F,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,oEAAoE,CAAC;KACjF,OAAO,CAAC,iBAAiB,EAAE,CAAC;KAC5B,MAAM,CAAC,mBAAmB,EAAE,iDAAiD,EAAE,MAAM,CAAC,CAAC;AAE1F,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAC5B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAC5B,yBAAyB,CAAC,OAAO,CAAC,CAAC;AACnC,yBAAyB,CAAC,OAAO,CAAC,CAAC;AACnC,0BAA0B,CAAC,OAAO,CAAC,CAAC;AACpC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAE9B,IAAI,CAAC,qBAAqB,EAAE,CAAC;IAC3B,4BAA4B,EAAE,CAAC;IAC/B,iBAAiB,EAAE,CAAC;IACpB,0BAA0B,EAAE,CAAC;AAC/B,CAAC;AACD,OAAO,CAAC,KAAK,EAAE,CAAC;AAChB,mBAAmB,EAAE,CAAC"}
|
package/dist/update-check.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ type InstallContext = "npx" | "global" | "local";
|
|
|
10
10
|
export declare function classifyInstallContext(selfPath: string, cwd: string): InstallContext;
|
|
11
11
|
export declare function getCurrentVersion(): string;
|
|
12
12
|
export declare function printUpdateBanner(): void;
|
|
13
|
+
export declare function printPluginHealthPreflight(): void;
|
|
13
14
|
/**
|
|
14
15
|
* Project #246 self-announcing shim: when the user runs a stale GLOBAL `@graphit/cli`
|
|
15
16
|
* directly (the plugin's PATH wrapper never shadows their interactive shell), tell
|
package/dist/update-check.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "fs";
|
|
2
|
+
import { spawnSync } from "child_process";
|
|
2
3
|
import { homedir } from "os";
|
|
3
|
-
import { join, sep } from "path";
|
|
4
|
+
import { dirname, join, sep } from "path";
|
|
4
5
|
import { fileURLToPath } from "url";
|
|
5
6
|
import { createRequire } from "module";
|
|
6
7
|
import { findOutdatedSkillInstalls, formatSkillStalenessBanner, } from "./skill-version.js";
|
|
@@ -131,6 +132,22 @@ export function printUpdateBanner() {
|
|
|
131
132
|
process.stderr.write(skillBanner);
|
|
132
133
|
}
|
|
133
134
|
}
|
|
135
|
+
export function printPluginHealthPreflight() {
|
|
136
|
+
if (process.env.GRAPHIT_SKIP_PLUGIN_PREFLIGHT === "1")
|
|
137
|
+
return;
|
|
138
|
+
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
139
|
+
const script = join(packageRoot, "scripts", "plugin-status.mjs");
|
|
140
|
+
if (!existsSync(script))
|
|
141
|
+
return;
|
|
142
|
+
const result = spawnSync(process.execPath, [script, "--preflight", "--repair", "--quiet", "--skip-network"], {
|
|
143
|
+
encoding: "utf-8",
|
|
144
|
+
timeout: 5000,
|
|
145
|
+
env: process.env,
|
|
146
|
+
});
|
|
147
|
+
if (result.stdout) {
|
|
148
|
+
process.stderr.write(result.stdout.endsWith("\n") ? result.stdout : `${result.stdout}\n`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
134
151
|
/**
|
|
135
152
|
* Project #246 self-announcing shim: when the user runs a stale GLOBAL `@graphit/cli`
|
|
136
153
|
* directly (the plugin's PATH wrapper never shadows their interactive shell), tell
|
package/dist/update-check.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-check.js","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACtF,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"update-check.js","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
chmodSync,
|
|
5
|
+
cpSync,
|
|
6
|
+
existsSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
readFileSync,
|
|
9
|
+
realpathSync,
|
|
10
|
+
renameSync,
|
|
11
|
+
rmSync,
|
|
12
|
+
writeFileSync,
|
|
13
|
+
} from "node:fs";
|
|
4
14
|
import { homedir } from "node:os";
|
|
5
|
-
import { delimiter, dirname, join } from "node:path";
|
|
15
|
+
import { delimiter, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
6
16
|
import { fileURLToPath } from "node:url";
|
|
7
17
|
|
|
8
18
|
// Project #246: GRAPHIT_REGISTRY_URL lets tests point at a local server and
|
|
@@ -10,6 +20,19 @@ import { fileURLToPath } from "node:url";
|
|
|
10
20
|
const REGISTRY_URL =
|
|
11
21
|
process.env.GRAPHIT_REGISTRY_URL ?? "https://registry.npmjs.org/@graphit/cli/latest";
|
|
12
22
|
const PACKAGE_NAME = "@graphit/cli";
|
|
23
|
+
const PLUGIN_ID = "graphit@graphit-plugin";
|
|
24
|
+
const CLAUDE_MARKETPLACE_NAME = "graphit-plugin";
|
|
25
|
+
const CLAUDE_PLUGIN_NAME = "graphit";
|
|
26
|
+
const REPAIRABLE_BUNDLE_ENTRIES = [
|
|
27
|
+
".claude-plugin",
|
|
28
|
+
".codex-plugin",
|
|
29
|
+
"skills",
|
|
30
|
+
"hooks",
|
|
31
|
+
"scripts",
|
|
32
|
+
"bin",
|
|
33
|
+
"README.md",
|
|
34
|
+
"package.json",
|
|
35
|
+
];
|
|
13
36
|
// Project #246: ~4h TTL (was 24h) so a single-source bump reaches returning
|
|
14
37
|
// sessions within one window (ARCH-2, PERF-2).
|
|
15
38
|
const TTL_MS = 4 * 60 * 60 * 1000;
|
|
@@ -19,6 +42,8 @@ const CACHE_SCHEMA_VERSION = 1;
|
|
|
19
42
|
// Strict semver. The wrapper enforces the same shape (SEC-6); keep them in sync.
|
|
20
43
|
const SEMVER_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
21
44
|
const args = new Set(process.argv.slice(2));
|
|
45
|
+
const shouldRepair = args.has("--repair") || args.has("--auto-repair");
|
|
46
|
+
const isPreflight = args.has("--preflight");
|
|
22
47
|
const hookIndex = process.argv.indexOf("--hook");
|
|
23
48
|
const hookEvent = hookIndex >= 0 ? process.argv[hookIndex + 1] : null;
|
|
24
49
|
const pluginRoot =
|
|
@@ -55,6 +80,28 @@ function readFrontmatterVersion(path) {
|
|
|
55
80
|
}
|
|
56
81
|
}
|
|
57
82
|
|
|
83
|
+
function readBundleInfo(root) {
|
|
84
|
+
const packageJson = tryReadJson(join(root, "package.json"));
|
|
85
|
+
const versionJson = tryReadJson(join(root, "skills", "graphit", "VERSION.json"));
|
|
86
|
+
const claudePlugin = tryReadJson(join(root, ".claude-plugin", "plugin.json"));
|
|
87
|
+
const marketplace = tryReadJson(join(root, ".claude-plugin", "marketplace.json"));
|
|
88
|
+
const marketplacePlugin = marketplace?.plugins?.find((plugin) => plugin.name === CLAUDE_PLUGIN_NAME);
|
|
89
|
+
return {
|
|
90
|
+
packageName: packageJson?.name ?? versionJson?.package ?? PACKAGE_NAME,
|
|
91
|
+
currentVersion:
|
|
92
|
+
packageJson?.version ??
|
|
93
|
+
versionJson?.version ??
|
|
94
|
+
claudePlugin?.version ??
|
|
95
|
+
marketplacePlugin?.version ??
|
|
96
|
+
marketplace?.metadata?.version ??
|
|
97
|
+
readFrontmatterVersion(join(root, "skills", "graphit", "SKILL.md")) ??
|
|
98
|
+
null,
|
|
99
|
+
claudePlugin: claudePlugin ?? null,
|
|
100
|
+
marketplace: marketplace ?? null,
|
|
101
|
+
marketplacePlugin: marketplacePlugin ?? null,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
58
105
|
function compareVersions(left, right) {
|
|
59
106
|
const leftParts = left.split(".").map(Number);
|
|
60
107
|
const rightParts = right.split(".").map(Number);
|
|
@@ -69,6 +116,23 @@ function compareVersions(left, right) {
|
|
|
69
116
|
return 0;
|
|
70
117
|
}
|
|
71
118
|
|
|
119
|
+
function versionIsBehind(version, currentVersion) {
|
|
120
|
+
if (!isStrictSemver(currentVersion)) return false;
|
|
121
|
+
if (!version || !isStrictSemver(version)) return true;
|
|
122
|
+
return compareVersions(version, currentVersion) < 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function sanitizePathPart(value) {
|
|
126
|
+
return value.replace(/[^a-zA-Z0-9\-_.]/g, "-");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function isWithinDirectory(child, parent) {
|
|
130
|
+
const parentResolved = resolve(parent);
|
|
131
|
+
const childResolved = resolve(child);
|
|
132
|
+
const rel = relative(parentResolved, childResolved);
|
|
133
|
+
return rel === "" || (!!rel && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel));
|
|
134
|
+
}
|
|
135
|
+
|
|
72
136
|
function copiedSkillTargets(home = homedir(), cwd = process.cwd()) {
|
|
73
137
|
return [
|
|
74
138
|
{ kind: "claude-code", label: "Claude Code global", scope: "global", path: join(home, ".claude", "skills", "graphit", "SKILL.md") },
|
|
@@ -136,6 +200,201 @@ function atomicWriteJson(path, obj) {
|
|
|
136
200
|
}
|
|
137
201
|
}
|
|
138
202
|
|
|
203
|
+
function claudePluginsRoot() {
|
|
204
|
+
return process.env.CLAUDE_PLUGINS_ROOT ?? join(homedir(), ".claude", "plugins");
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function claudeInstalledPluginsPath(root = claudePluginsRoot()) {
|
|
208
|
+
return join(root, "installed_plugins.json");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function claudeVersionedCachePath(version, root = claudePluginsRoot()) {
|
|
212
|
+
return join(
|
|
213
|
+
root,
|
|
214
|
+
"cache",
|
|
215
|
+
CLAUDE_MARKETPLACE_NAME,
|
|
216
|
+
CLAUDE_PLUGIN_NAME,
|
|
217
|
+
sanitizePathPart(version),
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function readClaudeInstalledFile(root = claudePluginsRoot()) {
|
|
222
|
+
const path = claudeInstalledPluginsPath(root);
|
|
223
|
+
const data = tryReadJson(path);
|
|
224
|
+
if (!data || typeof data !== "object") return null;
|
|
225
|
+
return { path, data };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function graphitInstallEntries(installedData) {
|
|
229
|
+
const plugins = installedData.plugins && typeof installedData.plugins === "object"
|
|
230
|
+
? installedData.plugins
|
|
231
|
+
: installedData;
|
|
232
|
+
const raw = plugins?.[PLUGIN_ID];
|
|
233
|
+
if (!raw) return [];
|
|
234
|
+
if (Array.isArray(raw)) {
|
|
235
|
+
return raw
|
|
236
|
+
.filter((entry) => entry && typeof entry === "object")
|
|
237
|
+
.map((entry) => ({ entry }));
|
|
238
|
+
}
|
|
239
|
+
if (typeof raw === "object") {
|
|
240
|
+
return [{ entry: raw }];
|
|
241
|
+
}
|
|
242
|
+
return [];
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function pluginEntryVersion(entry) {
|
|
246
|
+
if (!entry || typeof entry !== "object") return null;
|
|
247
|
+
const installPath = typeof entry.installPath === "string" ? entry.installPath : null;
|
|
248
|
+
const skillVersion = installPath
|
|
249
|
+
? readFrontmatterVersion(join(installPath, "skills", "graphit", "SKILL.md"))
|
|
250
|
+
: null;
|
|
251
|
+
const versionJson = installPath
|
|
252
|
+
? tryReadJson(join(installPath, "skills", "graphit", "VERSION.json"))?.version
|
|
253
|
+
: null;
|
|
254
|
+
return {
|
|
255
|
+
installPath,
|
|
256
|
+
entryVersion: typeof entry.version === "string" ? entry.version : null,
|
|
257
|
+
skillVersion,
|
|
258
|
+
versionJson: versionJson ?? null,
|
|
259
|
+
effectiveVersion: skillVersion ?? versionJson ?? (typeof entry.version === "string" ? entry.version : null),
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function repairSourceLooksCurrent(sourceRoot, currentVersion) {
|
|
264
|
+
if (!isStrictSemver(currentVersion)) return false;
|
|
265
|
+
const skillVersion = readFrontmatterVersion(join(sourceRoot, "skills", "graphit", "SKILL.md"));
|
|
266
|
+
const versionJson = tryReadJson(join(sourceRoot, "skills", "graphit", "VERSION.json"))?.version;
|
|
267
|
+
const claudePlugin = tryReadJson(join(sourceRoot, ".claude-plugin", "plugin.json"))?.version;
|
|
268
|
+
return skillVersion === currentVersion && versionJson === currentVersion && claudePlugin === currentVersion;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function copyRepairableBundle(sourceRoot, targetRoot) {
|
|
272
|
+
if (!isWithinDirectory(targetRoot, claudePluginsRoot())) {
|
|
273
|
+
throw new Error(`Refusing to repair outside Claude plugins directory: ${targetRoot}`);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const tmpRoot = `${targetRoot}.tmp-${process.pid}-${Date.now()}`;
|
|
277
|
+
rmSync(tmpRoot, { recursive: true, force: true });
|
|
278
|
+
mkdirSync(tmpRoot, { recursive: true });
|
|
279
|
+
try {
|
|
280
|
+
for (const entry of REPAIRABLE_BUNDLE_ENTRIES) {
|
|
281
|
+
const source = join(sourceRoot, entry);
|
|
282
|
+
if (!existsSync(source)) continue;
|
|
283
|
+
cpSync(source, join(tmpRoot, entry), {
|
|
284
|
+
recursive: true,
|
|
285
|
+
force: true,
|
|
286
|
+
verbatimSymlinks: true,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
try {
|
|
290
|
+
chmodSync(join(tmpRoot, "bin", "graphit"), 0o755);
|
|
291
|
+
} catch {
|
|
292
|
+
// Windows or missing wrapper; integrity checks catch real packaging drift.
|
|
293
|
+
}
|
|
294
|
+
mkdirSync(dirname(targetRoot), { recursive: true });
|
|
295
|
+
rmSync(targetRoot, { recursive: true, force: true });
|
|
296
|
+
renameSync(tmpRoot, targetRoot);
|
|
297
|
+
} catch (error) {
|
|
298
|
+
rmSync(tmpRoot, { recursive: true, force: true });
|
|
299
|
+
throw error;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function updateClaudeInstalledEntriesOnDisk(installedFile, staleRecords, targetPath, currentVersion) {
|
|
304
|
+
const now = new Date().toISOString();
|
|
305
|
+
for (const record of staleRecords) {
|
|
306
|
+
record.entry.installPath = targetPath;
|
|
307
|
+
record.entry.version = currentVersion;
|
|
308
|
+
record.entry.lastUpdated = now;
|
|
309
|
+
if (typeof record.entry.installedAt !== "string") {
|
|
310
|
+
record.entry.installedAt = now;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
atomicWriteJson(installedFile.path, installedFile.data);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function inspectClaudeInstalledPlugin(currentVersion, repair) {
|
|
317
|
+
const installedFile = readClaudeInstalledFile();
|
|
318
|
+
if (!installedFile) return { findings: [], metadata: [] };
|
|
319
|
+
|
|
320
|
+
const metadata = [];
|
|
321
|
+
const entries = graphitInstallEntries(installedFile.data);
|
|
322
|
+
if (entries.length === 0) return { findings: [], metadata };
|
|
323
|
+
|
|
324
|
+
const staleRecords = [];
|
|
325
|
+
for (const record of entries) {
|
|
326
|
+
const versionInfo = pluginEntryVersion(record.entry);
|
|
327
|
+
metadata.push({
|
|
328
|
+
label: `Claude Code installed ${PLUGIN_ID}`,
|
|
329
|
+
version: versionInfo.effectiveVersion,
|
|
330
|
+
installPath: versionInfo.installPath,
|
|
331
|
+
entryVersion: versionInfo.entryVersion,
|
|
332
|
+
skillVersion: versionInfo.skillVersion,
|
|
333
|
+
scope: record.entry.scope ?? "user",
|
|
334
|
+
projectPath: record.entry.projectPath ?? null,
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
if (
|
|
338
|
+
versionIsBehind(versionInfo.effectiveVersion, currentVersion) ||
|
|
339
|
+
versionIsBehind(versionInfo.entryVersion, currentVersion)
|
|
340
|
+
) {
|
|
341
|
+
staleRecords.push({ ...record, versionInfo });
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (staleRecords.length === 0) return { findings: [], metadata };
|
|
346
|
+
|
|
347
|
+
const staleVersions = [...new Set(staleRecords.map((record) => record.versionInfo.effectiveVersion ?? "unknown"))].join(", ");
|
|
348
|
+
const targetPath = claudeVersionedCachePath(currentVersion);
|
|
349
|
+
|
|
350
|
+
if (!repair) {
|
|
351
|
+
return {
|
|
352
|
+
metadata,
|
|
353
|
+
findings: [
|
|
354
|
+
{
|
|
355
|
+
type: "claude-installed-plugin-stale",
|
|
356
|
+
message: `Claude Code installed Graphit plugin is stale (${staleVersions}), expected ${currentVersion}`,
|
|
357
|
+
remediation: "Run `graphit plugin status --repair`, then restart/reload Claude Code. If you prefer the native plugin manager, run `/plugin marketplace update graphit-plugin`, then `/plugin update graphit@graphit-plugin`, then restart/reload.",
|
|
358
|
+
},
|
|
359
|
+
],
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
try {
|
|
364
|
+
if (!repairSourceLooksCurrent(pluginRoot, currentVersion)) {
|
|
365
|
+
throw new Error(`current npm/plugin bundle at ${pluginRoot} is missing synced ${currentVersion} plugin files`);
|
|
366
|
+
}
|
|
367
|
+
const targetSkillVersion = readFrontmatterVersion(join(targetPath, "skills", "graphit", "SKILL.md"));
|
|
368
|
+
if (targetSkillVersion !== currentVersion) {
|
|
369
|
+
copyRepairableBundle(pluginRoot, targetPath);
|
|
370
|
+
}
|
|
371
|
+
updateClaudeInstalledEntriesOnDisk(installedFile, staleRecords, targetPath, currentVersion);
|
|
372
|
+
return {
|
|
373
|
+
metadata,
|
|
374
|
+
findings: [
|
|
375
|
+
{
|
|
376
|
+
type: "claude-installed-plugin-repaired",
|
|
377
|
+
message: `Claude Code installed Graphit plugin was stale (${staleVersions}); repaired disk cache to ${currentVersion}`,
|
|
378
|
+
remediation: `Restart/reload Claude Code so it loads the repaired plugin cache at ${targetPath}. The already-running session may still have the old SKILL.md in memory until then.`,
|
|
379
|
+
repaired: true,
|
|
380
|
+
installPath: targetPath,
|
|
381
|
+
},
|
|
382
|
+
],
|
|
383
|
+
};
|
|
384
|
+
} catch (error) {
|
|
385
|
+
return {
|
|
386
|
+
metadata,
|
|
387
|
+
findings: [
|
|
388
|
+
{
|
|
389
|
+
type: "claude-installed-plugin-stale",
|
|
390
|
+
message: `Claude Code installed Graphit plugin is stale (${staleVersions}), expected ${currentVersion}; auto-repair failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
391
|
+
remediation: "Run `/plugin marketplace update graphit-plugin`, then `/plugin update graphit@graphit-plugin`, then restart/reload Claude Code. `graphit plugin status --repair` can repair from the npm bundle once the local files are writable.",
|
|
392
|
+
},
|
|
393
|
+
],
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
139
398
|
function writeCache(path, latestVersion) {
|
|
140
399
|
atomicWriteJson(path, {
|
|
141
400
|
schemaVersion: CACHE_SCHEMA_VERSION,
|
|
@@ -255,14 +514,31 @@ function tryParseJson(value) {
|
|
|
255
514
|
}
|
|
256
515
|
|
|
257
516
|
async function collectStatus() {
|
|
258
|
-
const
|
|
259
|
-
const
|
|
517
|
+
const bundleInfo = readBundleInfo(pluginRoot);
|
|
518
|
+
const packageName = bundleInfo.packageName;
|
|
519
|
+
const currentVersion = bundleInfo.currentVersion;
|
|
520
|
+
if (!currentVersion) {
|
|
521
|
+
return {
|
|
522
|
+
packageName,
|
|
523
|
+
sourceOfTruth: "plugin-bundle",
|
|
524
|
+
currentVersion: null,
|
|
525
|
+
latestVersion: null,
|
|
526
|
+
metadata: [],
|
|
527
|
+
findings: [
|
|
528
|
+
{
|
|
529
|
+
type: "metadata-drift",
|
|
530
|
+
message: `Could not determine Graphit plugin version from ${pluginRoot}`,
|
|
531
|
+
remediation: "Reinstall the Graphit plugin from the marketplace, then rerun `graphit plugin status`.",
|
|
532
|
+
},
|
|
533
|
+
],
|
|
534
|
+
};
|
|
535
|
+
}
|
|
260
536
|
const findings = [];
|
|
261
537
|
const metadata = [];
|
|
262
|
-
const claudePlugin =
|
|
538
|
+
const claudePlugin = bundleInfo.claudePlugin;
|
|
263
539
|
const codexPlugin = tryReadJson(join(pluginRoot, ".codex-plugin", "plugin.json"));
|
|
264
|
-
const marketplace =
|
|
265
|
-
const marketplacePlugin =
|
|
540
|
+
const marketplace = bundleInfo.marketplace;
|
|
541
|
+
const marketplacePlugin = bundleInfo.marketplacePlugin;
|
|
266
542
|
|
|
267
543
|
const versionChecks = [
|
|
268
544
|
[".claude-plugin/plugin.json", claudePlugin?.version],
|
|
@@ -277,7 +553,7 @@ async function collectStatus() {
|
|
|
277
553
|
];
|
|
278
554
|
|
|
279
555
|
for (const [label, version] of versionChecks) {
|
|
280
|
-
if (version !== currentVersion) {
|
|
556
|
+
if (!isPreflight && version !== currentVersion) {
|
|
281
557
|
findings.push({
|
|
282
558
|
type: "metadata-drift",
|
|
283
559
|
message: `${label} is ${version ?? "missing"}, expected ${currentVersion}`,
|
|
@@ -290,25 +566,25 @@ async function collectStatus() {
|
|
|
290
566
|
const marketplaceSource = marketplacePlugin?.source;
|
|
291
567
|
const sourceMatches =
|
|
292
568
|
marketplaceSource?.source === "npm" &&
|
|
293
|
-
marketplaceSource.package ===
|
|
569
|
+
marketplaceSource.package === packageName &&
|
|
294
570
|
marketplaceSource.version === currentVersion;
|
|
295
571
|
metadata.push({
|
|
296
572
|
label: ".claude-plugin/marketplace.json source",
|
|
297
573
|
version: marketplaceSource?.version ?? null,
|
|
298
574
|
source: marketplaceSource ?? null,
|
|
299
575
|
});
|
|
300
|
-
if (!sourceMatches) {
|
|
576
|
+
if (!isPreflight && !sourceMatches) {
|
|
301
577
|
findings.push({
|
|
302
578
|
type: "metadata-drift",
|
|
303
579
|
message: `.claude-plugin/marketplace.json source is ${
|
|
304
580
|
marketplaceSource ? JSON.stringify(marketplaceSource) : "missing"
|
|
305
|
-
}, expected npm source ${
|
|
581
|
+
}, expected npm source ${packageName}@${currentVersion}`,
|
|
306
582
|
remediation: "Run `npm run sync:version` before publishing @graphit/cli.",
|
|
307
583
|
});
|
|
308
584
|
}
|
|
309
585
|
|
|
310
586
|
const latestVersion = await getLatestVersion(currentVersion);
|
|
311
|
-
if (latestVersion && compareVersions(latestVersion, currentVersion) > 0) {
|
|
587
|
+
if (!isPreflight && latestVersion && compareVersions(latestVersion, currentVersion) > 0) {
|
|
312
588
|
findings.push({
|
|
313
589
|
type: "package-update",
|
|
314
590
|
message: `@graphit/cli update available: ${currentVersion} -> ${latestVersion}`,
|
|
@@ -316,6 +592,10 @@ async function collectStatus() {
|
|
|
316
592
|
});
|
|
317
593
|
}
|
|
318
594
|
|
|
595
|
+
const claudeInstall = inspectClaudeInstalledPlugin(currentVersion, shouldRepair);
|
|
596
|
+
metadata.push(...claudeInstall.metadata);
|
|
597
|
+
findings.push(...claudeInstall.findings);
|
|
598
|
+
|
|
319
599
|
for (const target of copiedSkillTargets()) {
|
|
320
600
|
const { label, path } = target;
|
|
321
601
|
if (!existsSync(path)) continue;
|
|
@@ -339,7 +619,7 @@ async function collectStatus() {
|
|
|
339
619
|
}
|
|
340
620
|
|
|
341
621
|
return {
|
|
342
|
-
packageName
|
|
622
|
+
packageName,
|
|
343
623
|
sourceOfTruth: "plugin-bundle",
|
|
344
624
|
currentVersion,
|
|
345
625
|
latestVersion,
|
package/skills/graphit/SKILL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: graphit
|
|
3
3
|
description: >-
|
|
4
4
|
Use Graphit for ANY question about the user's business or product data: metrics, KPIs, revenue, retention, spend, users, cohorts, funnels, trends, comparisons, "why did X change", "how are we doing on Y", analysis, reports, or dashboards. Activate even when the user does not say "Graphit" or name any tool: if someone wants to understand their numbers, this is the tool. Graphit answers through a governed semantic layer (computed the team's way, reusable and safe to share) and delivers the answer as a fast cached-data query or a hand-authored interactive HTML dashboard, and can create the metrics, dimensions, and rules an answer needs. Prefer Graphit over hand-rolled one-off analysis whenever the data is, or could be, the user's business data. Skip only for pure software tasks (code, logs, config, infra) or data with nothing to do with the user's business.
|
|
5
|
-
skill_version: "0.
|
|
5
|
+
skill_version: "0.2.0"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
<!-- SIZE EXEMPTION (SKILL.md): standard hard limit 12,288 chars, exempted ceiling 24,576. This router carries the always-loaded collaboration and pace-control spine (brainstorm, the ask-user tool, present-result, plan-next), the hard constraints including the scope gate, the investigation loop, and the auto-generated command table (between the COMMANDS markers, written by scripts/generate-commands-doc.mjs) - all needed on every turn, so by the co-load test they cannot be deferred to a reference. Command knowledge co-loads in particular: scoping, the readiness gate, querying, and delivery each need it. The marker sits after the YAML frontmatter (not before) so the skill loader and sync-plugin-version.mjs still parse the frontmatter. Reviewed 2026-06-18. -->
|
|
@@ -140,7 +140,7 @@ Read the one that matches what you are doing now. Do not preload them. Exact com
|
|
|
140
140
|
|
|
141
141
|
## Commands
|
|
142
142
|
|
|
143
|
-
Graphit is one CLI, but how you invoke it depends on your environment. On Claude Code the plugin provides a `graphit` wrapper, so `graphit <command>` runs the current CLI. On Codex, Cursor, a terminal, or CI there is no `graphit` wrapper - invoke the CLI explicitly with `npx -y @graphit/cli@0.
|
|
143
|
+
Graphit is one CLI, but how you invoke it depends on your environment. On Claude Code the plugin provides a `graphit` wrapper, so `graphit <command>` runs the current CLI. On Codex, Cursor, a terminal, or CI there is no `graphit` wrapper - invoke the CLI explicitly with `npx -y @graphit/cli@0.2.0 <command>` (a stamped version, kept current automatically by the build), or pin an exact one - `npx -y @graphit/cli@<exact> <command>` - for a reproducible run. The table below is the always-loaded command map, generated from the CLI itself, so it is the source of truth for which commands, subcommands, and flags exist. For exact flag values and full descriptions, run `graphit <command> --help` - never guess a flag.
|
|
144
144
|
|
|
145
145
|
<!-- COMMANDS:START -->
|
|
146
146
|
|
|
@@ -217,7 +217,7 @@ _Generated from the CLI by `npm run gen:commands` - do not hand-edit between the
|
|
|
217
217
|
- `team list` - List teams you belong to (org admins see all teams)
|
|
218
218
|
|
|
219
219
|
**plugin** - Inspect Graphit assistant plugin status
|
|
220
|
-
- `plugin status` - Check plugin/package/skill version health - `--json --quiet --skip-network`
|
|
220
|
+
- `plugin status` - Check plugin/package/skill version health - `--json --quiet --skip-network --repair`
|
|
221
221
|
|
|
222
222
|
**setup** - Install legacy copied Graphit assistant files for Cursor or fallback setups
|
|
223
223
|
- `setup` - Install legacy copied Graphit assistant files for Cursor or fallback setups - `--editor --project --update --legacy-copy --remove-legacy-copies --dry-run`
|