@tryglen/cli 0.24.6 → 0.24.8
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 +12 -0
- package/dist/_utils/codex-hooks-setup.d.ts +6 -1
- package/dist/_utils/codex-hooks-setup.js +34 -11
- package/dist/_utils/codex-hooks-setup.js.map +1 -1
- package/dist/_utils/ensure-global-cli.d.ts +0 -3
- package/dist/_utils/ensure-global-cli.js +52 -20
- package/dist/_utils/ensure-global-cli.js.map +1 -1
- package/dist/_utils/git-hook-setup.d.ts +10 -1
- package/dist/_utils/git-hook-setup.js +54 -2
- package/dist/_utils/git-hook-setup.js.map +1 -1
- package/dist/_utils/install-receipt.d.ts +32 -0
- package/dist/_utils/install-receipt.js +126 -0
- package/dist/_utils/install-receipt.js.map +1 -0
- package/dist/_utils/purge-agent-plugins.d.ts +8 -0
- package/dist/_utils/purge-agent-plugins.js +62 -0
- package/dist/_utils/purge-agent-plugins.js.map +1 -0
- package/dist/_utils/purge-claude-statusline.d.ts +12 -0
- package/dist/_utils/purge-claude-statusline.js +57 -0
- package/dist/_utils/purge-claude-statusline.js.map +1 -0
- package/dist/_utils/purge-local-state.d.ts +7 -0
- package/dist/_utils/purge-local-state.js +40 -0
- package/dist/_utils/purge-local-state.js.map +1 -0
- package/dist/bin.js +1 -1
- package/dist/bin.js.map +1 -1
- package/dist/commands/install.js +39 -53
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/uninstall.d.ts +6 -9
- package/dist/commands/uninstall.js +104 -54
- package/dist/commands/uninstall.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,6 +23,7 @@ glen login
|
|
|
23
23
|
| `glen org switch [slug]` | Switch the active organization for this machine (interactive picker without `slug`). |
|
|
24
24
|
| `glen ingest [--agent <name>]` | Ingest a turn from stdin — used by agent hooks (`claude-code`, `codex`, `cursor`, or `pi`). |
|
|
25
25
|
| `glen install [--agent <claude\|codex\|cursor\|pi>]` | Set up or update glen for detected coding agents (plugin + hooks); idempotent, so re-running repairs a broken setup. `--claude-path <path>` / `--codex-path <path>` / `--pi-path <path>` point at a binary when auto-detection fails. |
|
|
26
|
+
| `glen uninstall` | Permanently remove Glen's local plugins, marketplaces, hooks, PATH entries, credentials, state, caches, and global npm CLI. |
|
|
26
27
|
| `glen update` | Update the glen CLI **and** any installed glen plugins, and re-verify the Codex hook registration. Never installs a plugin that isn't already installed — that's `glen install`'s job. |
|
|
27
28
|
| `glen doctor [--auto]` | Print machine-readable `status:` lines (CLI version/latest/channel, login + org, per-agent plugin + hook state) plus `→` remedy lines — the setup skill branches on them. `--auto` runs background updates silently (used by hooks). |
|
|
28
29
|
| `glen statusline` | Output a single status line for the agent's UI status bar — used by hooks. |
|
|
@@ -38,6 +39,17 @@ glen login
|
|
|
38
39
|
|
|
39
40
|
The state file is what the CLI sends as `x-glen-org-id` / `x-glen-incognito` headers on every request. The server validates org membership on every call — no state is stored server-side.
|
|
40
41
|
|
|
42
|
+
## Uninstall
|
|
43
|
+
|
|
44
|
+
`glen uninstall` permanently removes Glen's local agent plugins, marketplaces,
|
|
45
|
+
hooks, PATH entries, credentials, state, caches, and global npm CLI. It preserves
|
|
46
|
+
source repositories, agent transcripts, and cloud account/team data.
|
|
47
|
+
|
|
48
|
+
Cursor plugins must be removed in Cursor's plugin settings because Cursor does
|
|
49
|
+
not expose a supported plugin-removal CLI. If Cursor is detected, the command
|
|
50
|
+
reports the exact manual step and exits nonzero until that editor-managed residue
|
|
51
|
+
is addressed.
|
|
52
|
+
|
|
41
53
|
## Environment variables
|
|
42
54
|
|
|
43
55
|
| Variable | Default | Description |
|
|
@@ -4,5 +4,10 @@ declare const installCodexHooks: () => Promise<Result<{
|
|
|
4
4
|
trusted: boolean;
|
|
5
5
|
backedUp: boolean;
|
|
6
6
|
}, string>>;
|
|
7
|
-
declare const uninstallCodexHooks: (
|
|
7
|
+
declare const uninstallCodexHooks: (snapshot?: {
|
|
8
|
+
readonly hooksPath: string;
|
|
9
|
+
readonly hooksExisted: boolean;
|
|
10
|
+
readonly configPath: string;
|
|
11
|
+
readonly configExisted: boolean;
|
|
12
|
+
}) => Promise<Result<void, string>>;
|
|
8
13
|
export { installCodexHooks, isCodexHooksInstalled, uninstallCodexHooks };
|
|
@@ -4,6 +4,7 @@ import { listCodexHooks } from "./codex-app-server.js";
|
|
|
4
4
|
import { GLEN_OWNER_PREFIX, normalizeHooksFile, stripGlenHooks, withGlenHooks, } from "./codex-hooks-merge.js";
|
|
5
5
|
import { codexConfigTomlPath, codexHooksJsonPath } from "./codex-paths.js";
|
|
6
6
|
import { removeTrustBlocks, upsertTrustBlocks } from "./codex-trust-toml.js";
|
|
7
|
+
import { installReceipt } from "./install-receipt.js";
|
|
7
8
|
import { err, fromPromise, ok } from "./result.js";
|
|
8
9
|
import { statePath } from "./state.js";
|
|
9
10
|
// Marker recording that THIS machine opted into glen's codex hooks (gates
|
|
@@ -46,8 +47,7 @@ const atomicWrite = async (filePath, content) => {
|
|
|
46
47
|
// missing file from an empty one. Unparseable → backed up during install
|
|
47
48
|
// (never clobber another tool's data silently) and treated as empty;
|
|
48
49
|
// uninstall passes backupOnUnparseable=false and skips the rewrite instead.
|
|
49
|
-
const readExistingHooks = async (backupOnUnparseable) => {
|
|
50
|
-
const hooksPath = codexHooksJsonPath();
|
|
50
|
+
const readExistingHooks = async (backupOnUnparseable, hooksPath = codexHooksJsonPath()) => {
|
|
51
51
|
const raw = await fromPromise(readFile(hooksPath, "utf-8"));
|
|
52
52
|
if (!raw.ok)
|
|
53
53
|
return ok({ file: { hooks: {} }, backedUp: false, absent: true });
|
|
@@ -82,6 +82,8 @@ const trustGlenHooks = async () => {
|
|
|
82
82
|
return w.ok ? entries.map((e) => e.key) : [];
|
|
83
83
|
};
|
|
84
84
|
const installCodexHooks = async () => {
|
|
85
|
+
const hooksBefore = await fromPromise(readFile(codexHooksJsonPath(), "utf-8"));
|
|
86
|
+
const configBefore = await fromPromise(readFile(codexConfigTomlPath(), "utf-8"));
|
|
85
87
|
const existing = await readExistingHooks(true);
|
|
86
88
|
if (!existing.ok)
|
|
87
89
|
return existing;
|
|
@@ -95,6 +97,14 @@ const installCodexHooks = async () => {
|
|
|
95
97
|
const m = await atomicWrite(markerPath(), `${JSON.stringify({ installedAt: new Date().toISOString(), trustedKeys }, null, 2)}\n`);
|
|
96
98
|
if (!m.ok)
|
|
97
99
|
return err(`could not write install marker ${markerPath()}`);
|
|
100
|
+
const receipt = await installReceipt.recordCodexFiles({
|
|
101
|
+
hooksPath: codexHooksJsonPath(),
|
|
102
|
+
hooksExisted: hooksBefore.ok,
|
|
103
|
+
configPath: codexConfigTomlPath(),
|
|
104
|
+
configExisted: configBefore.ok,
|
|
105
|
+
});
|
|
106
|
+
if (!receipt.ok)
|
|
107
|
+
return err("could not write codex uninstall receipt");
|
|
98
108
|
return ok({
|
|
99
109
|
trusted: trustedKeys.length > 0,
|
|
100
110
|
backedUp: existing.value.backedUp,
|
|
@@ -102,26 +112,31 @@ const installCodexHooks = async () => {
|
|
|
102
112
|
};
|
|
103
113
|
// Removes glen's trust blocks from config.toml (no-op when the file is
|
|
104
114
|
// unreadable or there is nothing to remove).
|
|
105
|
-
const removeGlenTrustBlocks = async (keys) => {
|
|
115
|
+
const removeGlenTrustBlocks = async (keys, tomlPath = codexConfigTomlPath(), deleteIfEmpty = false) => {
|
|
106
116
|
if (keys.length === 0)
|
|
107
117
|
return ok(undefined);
|
|
108
|
-
const tomlPath = codexConfigTomlPath();
|
|
109
118
|
const raw = await fromPromise(readFile(tomlPath, "utf-8"));
|
|
110
119
|
if (!raw.ok)
|
|
111
120
|
return ok(undefined);
|
|
112
121
|
const updated = removeTrustBlocks(raw.value, keys);
|
|
122
|
+
if (deleteIfEmpty && updated.trim().length === 0) {
|
|
123
|
+
const removed = await fromPromise(unlink(tomlPath));
|
|
124
|
+
return removed.ok ? ok(undefined) : err(`could not remove ${tomlPath}`);
|
|
125
|
+
}
|
|
113
126
|
const w = await atomicWrite(tomlPath, updated);
|
|
114
127
|
return w.ok ? ok(undefined) : err(`could not write ${tomlPath}`);
|
|
115
128
|
};
|
|
116
|
-
const uninstallCodexHooks = async () => {
|
|
129
|
+
const uninstallCodexHooks = async (snapshot) => {
|
|
130
|
+
const hooksPath = snapshot?.hooksPath ?? codexHooksJsonPath();
|
|
131
|
+
const configPath = snapshot?.configPath ?? codexConfigTomlPath();
|
|
117
132
|
const marker = await readMarker();
|
|
118
|
-
const existing = await readExistingHooks(false);
|
|
133
|
+
const existing = await readExistingHooks(false, hooksPath);
|
|
119
134
|
if (!existing.ok)
|
|
120
135
|
return existing;
|
|
121
136
|
// Clean machine (no hooks.json): never touch ~/.codex or spawn the
|
|
122
137
|
// app-server — only remove marker-recorded trust blocks if any.
|
|
123
138
|
if (existing.value.absent) {
|
|
124
|
-
const t = await removeGlenTrustBlocks(marker?.trustedKeys ?? []);
|
|
139
|
+
const t = await removeGlenTrustBlocks(marker?.trustedKeys ?? [], configPath, snapshot?.configExisted === false);
|
|
125
140
|
if (!t.ok)
|
|
126
141
|
return t;
|
|
127
142
|
await fromPromise(unlink(markerPath()));
|
|
@@ -138,11 +153,19 @@ const uninstallCodexHooks = async () => {
|
|
|
138
153
|
// "skip") → leave it alone; still clean up trust blocks + marker.
|
|
139
154
|
if (!existing.value.backedUp) {
|
|
140
155
|
const stripped = stripGlenHooks(existing.value.file);
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
156
|
+
if (snapshot?.hooksExisted === false &&
|
|
157
|
+
Object.keys(stripped.hooks).length === 0) {
|
|
158
|
+
const removed = await fromPromise(unlink(hooksPath));
|
|
159
|
+
if (!removed.ok)
|
|
160
|
+
return err(`could not remove ${hooksPath}`);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
const w = await atomicWrite(hooksPath, `${JSON.stringify(stripped, null, 2)}\n`);
|
|
164
|
+
if (!w.ok)
|
|
165
|
+
return err(`could not write ${hooksPath}`);
|
|
166
|
+
}
|
|
144
167
|
}
|
|
145
|
-
const t = await removeGlenTrustBlocks(keys);
|
|
168
|
+
const t = await removeGlenTrustBlocks(keys, configPath, snapshot?.configExisted === false);
|
|
146
169
|
if (!t.ok)
|
|
147
170
|
return t;
|
|
148
171
|
await fromPromise(unlink(markerPath()));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-hooks-setup.js","sourceRoot":"","sources":["../../src/_utils/codex-hooks-setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EACL,iBAAiB,EAEjB,kBAAkB,EAClB,cAAc,EACd,aAAa,GACd,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAe,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,0EAA0E;AAC1E,wEAAwE;AACxE,4EAA4E;AAC5E,MAAM,UAAU,GAAG,GAAW,EAAE,CAC9B,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,4BAA4B,CAAC,CAAC;AAE3D,MAAM,SAAS,GAAG,CAAC,GAAW,EAAW,EAAE;IACzC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,sEAAsE;AACtE,6DAA6D;AAC7D,MAAM,UAAU,GAAG,KAAK,IAA+C,EAAE;IACvE,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/D,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAqC,CAAC;IACxE,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC;QACpD,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;QACtE,CAAC,CAAC,EAAE,CAAC;IACP,OAAO,EAAE,WAAW,EAAE,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,KAAK,IAAsB,EAAE,CACzD,CAAC,MAAM,UAAU,EAAE,CAAC,KAAK,IAAI,CAAC;AAEhC,MAAM,WAAW,GAAG,KAAK,EACvB,QAAgB,EAChB,OAAe,EACiB,EAAE;IAClC,MAAM,EAAE,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC5E,IAAI,CAAC,EAAE,CAAC,EAAE;QAAE,OAAO,EAAE,CAAC;IACtB,2EAA2E;IAC3E,MAAM,GAAG,GAAG,GAAG,QAAQ,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;IAC7C,MAAM,CAAC,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IACrD,IAAI,CAAC,CAAC,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC;IACpB,OAAO,WAAW,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF,uEAAuE;AACvE,yEAAyE;AACzE,qEAAqE;AACrE,4EAA4E;AAC5E,MAAM,iBAAiB,GAAG,KAAK,EAC7B,mBAA4B,
|
|
1
|
+
{"version":3,"file":"codex-hooks-setup.js","sourceRoot":"","sources":["../../src/_utils/codex-hooks-setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
2
|
import { realpathSync } from "node:fs";
|
|
3
|
-
import { join } from "node:path";
|
|
3
|
+
import { basename, dirname, isAbsolute, join } from "node:path";
|
|
4
4
|
import { newer } from "./update.js";
|
|
5
5
|
import { cliVersion } from "./version.js";
|
|
6
6
|
import { isInstalled } from "./which.js";
|
|
@@ -55,22 +55,30 @@ const versionAt = (glenPath) => {
|
|
|
55
55
|
return null;
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
// Use the literal public npm shim on PATH, not its realpath: runtimes such as
|
|
59
|
+
// Vite+ expose `<prefix>/bin/npm` while resolving that shim into a private Node
|
|
60
|
+
// runtime whose configured npm-global prefix is intentionally not public.
|
|
61
|
+
const npmGlobalTarget = () => {
|
|
60
62
|
try {
|
|
61
|
-
const
|
|
63
|
+
const npmPath = execFileSync("which", ["npm"], {
|
|
62
64
|
encoding: "utf8",
|
|
63
65
|
timeout: 10_000,
|
|
64
66
|
}).trim();
|
|
65
|
-
|
|
67
|
+
if (!isAbsolute(npmPath) || basename(npmPath) !== "npm")
|
|
68
|
+
return null;
|
|
69
|
+
const binDir = dirname(npmPath);
|
|
70
|
+
if (basename(binDir) !== "bin")
|
|
71
|
+
return null;
|
|
72
|
+
const prefix = dirname(binDir);
|
|
73
|
+
return { npmPath, prefix, binDir, glenPath: join(binDir, "glen") };
|
|
66
74
|
}
|
|
67
75
|
catch {
|
|
68
76
|
return null;
|
|
69
77
|
}
|
|
70
78
|
};
|
|
71
|
-
const installGlobally = () => {
|
|
79
|
+
const installGlobally = (target) => {
|
|
72
80
|
try {
|
|
73
|
-
execFileSync(
|
|
81
|
+
execFileSync(target.npmPath, ["install", "-g", "--prefix", target.prefix, "@tryglen/cli@latest"], {
|
|
74
82
|
stdio: ["ignore", "ignore", "pipe"],
|
|
75
83
|
encoding: "utf8",
|
|
76
84
|
timeout: 300_000,
|
|
@@ -78,10 +86,16 @@ const installGlobally = () => {
|
|
|
78
86
|
return { ok: true, permission: false };
|
|
79
87
|
}
|
|
80
88
|
catch (error) {
|
|
81
|
-
const
|
|
82
|
-
?
|
|
83
|
-
:
|
|
84
|
-
|
|
89
|
+
const details = error && typeof error === "object"
|
|
90
|
+
? error
|
|
91
|
+
: {};
|
|
92
|
+
const diagnostic = [details.code, details.message, details.stderr]
|
|
93
|
+
.map((value) => String(value ?? ""))
|
|
94
|
+
.join("\n");
|
|
95
|
+
return {
|
|
96
|
+
ok: false,
|
|
97
|
+
permission: /EACCES|permission denied/i.test(diagnostic),
|
|
98
|
+
};
|
|
85
99
|
}
|
|
86
100
|
};
|
|
87
101
|
/**
|
|
@@ -108,7 +122,15 @@ const ensureGlobalCli = (onInstallStart) => {
|
|
|
108
122
|
if (!isInstalled("npm"))
|
|
109
123
|
return { status: "no-npm" };
|
|
110
124
|
onInstallStart?.(existing !== null);
|
|
111
|
-
const
|
|
125
|
+
const target = npmGlobalTarget();
|
|
126
|
+
if (!target) {
|
|
127
|
+
return {
|
|
128
|
+
status: "failed",
|
|
129
|
+
permission: false,
|
|
130
|
+
hadExisting: existing !== null,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const result = installGlobally(target);
|
|
112
134
|
if (!result.ok) {
|
|
113
135
|
return {
|
|
114
136
|
status: "failed",
|
|
@@ -116,14 +138,24 @@ const ensureGlobalCli = (onInstallStart) => {
|
|
|
116
138
|
hadExisting: existing !== null,
|
|
117
139
|
};
|
|
118
140
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
141
|
+
const installedVersion = versionAt(target.glenPath);
|
|
142
|
+
if (!installedVersion || newer(cliVersion, installedVersion)) {
|
|
143
|
+
return {
|
|
144
|
+
status: "failed",
|
|
145
|
+
permission: false,
|
|
146
|
+
hadExisting: existing !== null,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const resolved = persistentGlenPath();
|
|
150
|
+
const resolvedVersion = resolved ? versionAt(resolved) : null;
|
|
151
|
+
if (!resolvedVersion || newer(cliVersion, resolvedVersion)) {
|
|
152
|
+
return {
|
|
153
|
+
status: "failed",
|
|
154
|
+
permission: false,
|
|
155
|
+
hadExisting: existing !== null,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
return existing ? { status: "updated" } : { status: "installed" };
|
|
127
159
|
};
|
|
128
160
|
export { ensureGlobalCli };
|
|
129
161
|
//# sourceMappingURL=ensure-global-cli.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ensure-global-cli.js","sourceRoot":"","sources":["../../src/_utils/ensure-global-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"ensure-global-cli.js","sourceRoot":"","sources":["../../src/_utils/ensure-global-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,4 +6,13 @@ declare const installPrepareCommitMsgHook: (input: {
|
|
|
6
6
|
installed: boolean;
|
|
7
7
|
chained: boolean;
|
|
8
8
|
}, string>>;
|
|
9
|
-
|
|
9
|
+
declare const uninstallPrepareCommitMsgHook: (input: {
|
|
10
|
+
cwd: string;
|
|
11
|
+
snapshot?: {
|
|
12
|
+
readonly path: string;
|
|
13
|
+
readonly existed: boolean;
|
|
14
|
+
readonly before: string | null;
|
|
15
|
+
readonly installedHash: string;
|
|
16
|
+
};
|
|
17
|
+
}) => Promise<Result<void, string>>;
|
|
18
|
+
export { installPrepareCommitMsgHook, uninstallPrepareCommitMsgHook };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
|
-
import {
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { chmod, mkdir, readFile, rename, unlink, writeFile, } from "node:fs/promises";
|
|
3
4
|
import { dirname, isAbsolute, join } from "node:path";
|
|
5
|
+
import { installReceipt } from "./install-receipt.js";
|
|
4
6
|
import { err, fromPromise, ok } from "./result.js";
|
|
5
7
|
const GLEN_MARK = "# glen commit-anchor hook";
|
|
6
8
|
const git = (cwd, args) => {
|
|
@@ -58,7 +60,57 @@ const installPrepareCommitMsgHook = async (input) => {
|
|
|
58
60
|
const mv = await fromPromise(rename(tmp, hookPath));
|
|
59
61
|
if (!mv.ok)
|
|
60
62
|
return err("could not install hook");
|
|
63
|
+
const receipt = await installReceipt.recordGitHook({
|
|
64
|
+
path: hookPath,
|
|
65
|
+
existed: existing.ok,
|
|
66
|
+
before: existing.ok ? existing.value : null,
|
|
67
|
+
installedHash: createHash("sha256").update(script).digest("hex"),
|
|
68
|
+
});
|
|
69
|
+
if (!receipt.ok)
|
|
70
|
+
return err("could not record git hook for uninstall");
|
|
61
71
|
return ok({ installed: true, chained });
|
|
62
72
|
};
|
|
63
|
-
|
|
73
|
+
const uninstallPrepareCommitMsgHook = async (input) => {
|
|
74
|
+
const dir = input.snapshot
|
|
75
|
+
? dirname(input.snapshot.path)
|
|
76
|
+
: hooksDir(input.cwd);
|
|
77
|
+
if (!dir)
|
|
78
|
+
return ok(undefined);
|
|
79
|
+
const hookPath = input.snapshot?.path ?? join(dir, "prepare-commit-msg");
|
|
80
|
+
const backupPath = `${hookPath}.glen-bak`;
|
|
81
|
+
const current = await fromPromise(readFile(hookPath, "utf8"));
|
|
82
|
+
if (!current.ok) {
|
|
83
|
+
return current.error.code === "ENOENT"
|
|
84
|
+
? ok(undefined)
|
|
85
|
+
: err(`could not read ${hookPath}`);
|
|
86
|
+
}
|
|
87
|
+
if (input.snapshot &&
|
|
88
|
+
createHash("sha256").update(current.value).digest("hex") !==
|
|
89
|
+
input.snapshot.installedHash)
|
|
90
|
+
return err(`${hookPath} changed after Glen installed; remove its Glen lines manually`);
|
|
91
|
+
if (!current.value.includes(GLEN_MARK))
|
|
92
|
+
return ok(undefined);
|
|
93
|
+
if (input.snapshot?.existed && input.snapshot.before !== null) {
|
|
94
|
+
const temp = `${hookPath}.${process.pid}.tmp`;
|
|
95
|
+
const written = await fromPromise(writeFile(temp, input.snapshot.before));
|
|
96
|
+
if (!written.ok)
|
|
97
|
+
return err(`could not restore ${hookPath}`);
|
|
98
|
+
const secured = await fromPromise(chmod(temp, 0o755));
|
|
99
|
+
if (!secured.ok)
|
|
100
|
+
return err(`could not chmod restored ${hookPath}`);
|
|
101
|
+
const moved = await fromPromise(rename(temp, hookPath));
|
|
102
|
+
if (!moved.ok)
|
|
103
|
+
return err(`could not restore ${hookPath}`);
|
|
104
|
+
await fromPromise(unlink(backupPath));
|
|
105
|
+
return ok(undefined);
|
|
106
|
+
}
|
|
107
|
+
const backup = await fromPromise(readFile(backupPath, "utf8"));
|
|
108
|
+
if (backup.ok) {
|
|
109
|
+
const restored = await fromPromise(rename(backupPath, hookPath));
|
|
110
|
+
return restored.ok ? ok(undefined) : err(`could not restore ${hookPath}`);
|
|
111
|
+
}
|
|
112
|
+
const removed = await fromPromise(unlink(hookPath));
|
|
113
|
+
return removed.ok ? ok(undefined) : err(`could not remove ${hookPath}`);
|
|
114
|
+
};
|
|
115
|
+
export { installPrepareCommitMsgHook, uninstallPrepareCommitMsgHook };
|
|
64
116
|
//# sourceMappingURL=git-hook-setup.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-hook-setup.js","sourceRoot":"","sources":["../../src/_utils/git-hook-setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"git-hook-setup.js","sourceRoot":"","sources":["../../src/_utils/git-hook-setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type Result } from "./result.js";
|
|
2
|
+
type FileSnapshot = {
|
|
3
|
+
readonly path: string;
|
|
4
|
+
readonly existed: boolean;
|
|
5
|
+
readonly before: string | null;
|
|
6
|
+
readonly installedHash: string;
|
|
7
|
+
};
|
|
8
|
+
type CodexFilesSnapshot = {
|
|
9
|
+
readonly hooksPath: string;
|
|
10
|
+
readonly hooksExisted: boolean;
|
|
11
|
+
readonly configPath: string;
|
|
12
|
+
readonly configExisted: boolean;
|
|
13
|
+
};
|
|
14
|
+
type InstallReceipt = {
|
|
15
|
+
readonly version: 1;
|
|
16
|
+
readonly shellProfiles: string[];
|
|
17
|
+
readonly claudeSettings: FileSnapshot | null;
|
|
18
|
+
readonly codexFiles: CodexFilesSnapshot | null;
|
|
19
|
+
readonly gitHooks: FileSnapshot[];
|
|
20
|
+
readonly statePaths: string[];
|
|
21
|
+
};
|
|
22
|
+
declare const installReceipt: {
|
|
23
|
+
path: () => string;
|
|
24
|
+
read: () => Promise<InstallReceipt | null>;
|
|
25
|
+
recordShellProfile: (path: string) => Promise<Result<void, unknown>>;
|
|
26
|
+
recordClaudeSettings: (snapshot: FileSnapshot) => Promise<Result<void, unknown>>;
|
|
27
|
+
recordCodexFiles: (snapshot: CodexFilesSnapshot) => Promise<Result<void, unknown>>;
|
|
28
|
+
recordGitHook: (snapshot: FileSnapshot) => Promise<Result<void, unknown>>;
|
|
29
|
+
recordStatePath: (path: string) => Promise<Result<void, unknown>>;
|
|
30
|
+
remove: () => Promise<Result<void, unknown>>;
|
|
31
|
+
};
|
|
32
|
+
export { installReceipt };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { chmod, mkdir, readFile, rename, unlink, writeFile, } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fromPromise, ok } from "./result.js";
|
|
5
|
+
const receiptPath = () => process.env.GLEN_INSTALL_RECEIPT_PATH ??
|
|
6
|
+
join(homedir(), ".glen", "install-receipt.json");
|
|
7
|
+
const emptyReceipt = () => ({
|
|
8
|
+
version: 1,
|
|
9
|
+
shellProfiles: [],
|
|
10
|
+
claudeSettings: null,
|
|
11
|
+
codexFiles: null,
|
|
12
|
+
gitHooks: [],
|
|
13
|
+
statePaths: [],
|
|
14
|
+
});
|
|
15
|
+
const isFileSnapshot = (value) => {
|
|
16
|
+
if (!value || typeof value !== "object")
|
|
17
|
+
return false;
|
|
18
|
+
const item = value;
|
|
19
|
+
return (typeof item.path === "string" &&
|
|
20
|
+
typeof item.existed === "boolean" &&
|
|
21
|
+
(typeof item.before === "string" || item.before === null) &&
|
|
22
|
+
typeof item.installedHash === "string");
|
|
23
|
+
};
|
|
24
|
+
const parseReceipt = (raw) => {
|
|
25
|
+
const parsed = (() => {
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(raw);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
})();
|
|
33
|
+
if (!parsed || typeof parsed !== "object")
|
|
34
|
+
return null;
|
|
35
|
+
const value = parsed;
|
|
36
|
+
if (value.version !== 1)
|
|
37
|
+
return null;
|
|
38
|
+
if (!Array.isArray(value.shellProfiles))
|
|
39
|
+
return null;
|
|
40
|
+
if (!value.shellProfiles.every((item) => typeof item === "string"))
|
|
41
|
+
return null;
|
|
42
|
+
if (value.claudeSettings !== null && !isFileSnapshot(value.claudeSettings))
|
|
43
|
+
return null;
|
|
44
|
+
if (!Array.isArray(value.gitHooks) || !value.gitHooks.every(isFileSnapshot))
|
|
45
|
+
return null;
|
|
46
|
+
if (!Array.isArray(value.statePaths))
|
|
47
|
+
return null;
|
|
48
|
+
if (!value.statePaths.every((item) => typeof item === "string"))
|
|
49
|
+
return null;
|
|
50
|
+
const codex = value.codexFiles;
|
|
51
|
+
if (codex !== null &&
|
|
52
|
+
(!codex ||
|
|
53
|
+
typeof codex !== "object" ||
|
|
54
|
+
typeof codex.hooksPath !== "string" ||
|
|
55
|
+
typeof codex.hooksExisted !== "boolean" ||
|
|
56
|
+
typeof codex.configPath !== "string" ||
|
|
57
|
+
typeof codex.configExisted !== "boolean"))
|
|
58
|
+
return null;
|
|
59
|
+
return value;
|
|
60
|
+
};
|
|
61
|
+
const read = async () => {
|
|
62
|
+
const result = await fromPromise(readFile(receiptPath(), "utf8"));
|
|
63
|
+
return result.ok ? parseReceipt(result.value) : null;
|
|
64
|
+
};
|
|
65
|
+
const write = async (receipt) => {
|
|
66
|
+
const path = receiptPath();
|
|
67
|
+
const dir = dirname(path);
|
|
68
|
+
const made = await fromPromise(mkdir(dir, { recursive: true, mode: 0o700 }));
|
|
69
|
+
if (!made.ok)
|
|
70
|
+
return made;
|
|
71
|
+
const securedDir = await fromPromise(chmod(dir, 0o700));
|
|
72
|
+
if (!securedDir.ok)
|
|
73
|
+
return securedDir;
|
|
74
|
+
const temp = `${path}.${process.pid}.tmp`;
|
|
75
|
+
const written = await fromPromise(writeFile(temp, `${JSON.stringify(receipt, null, 2)}\n`, { mode: 0o600 }));
|
|
76
|
+
if (!written.ok)
|
|
77
|
+
return written;
|
|
78
|
+
const securedFile = await fromPromise(chmod(temp, 0o600));
|
|
79
|
+
if (!securedFile.ok)
|
|
80
|
+
return securedFile;
|
|
81
|
+
return fromPromise(rename(temp, path));
|
|
82
|
+
};
|
|
83
|
+
const update = async (change) => write(change((await read()) ?? emptyReceipt()));
|
|
84
|
+
const recordClaudeSettings = async (snapshot) => update((current) => ({
|
|
85
|
+
...current,
|
|
86
|
+
claudeSettings: current.claudeSettings
|
|
87
|
+
? { ...current.claudeSettings, installedHash: snapshot.installedHash }
|
|
88
|
+
: snapshot,
|
|
89
|
+
}));
|
|
90
|
+
const recordCodexFiles = async (snapshot) => update((current) => ({
|
|
91
|
+
...current,
|
|
92
|
+
codexFiles: current.codexFiles ?? snapshot,
|
|
93
|
+
}));
|
|
94
|
+
const recordGitHook = async (snapshot) => update((current) => {
|
|
95
|
+
const prior = current.gitHooks.find((hook) => hook.path === snapshot.path);
|
|
96
|
+
const gitHooks = prior
|
|
97
|
+
? current.gitHooks.map((hook) => hook.path === snapshot.path
|
|
98
|
+
? { ...hook, installedHash: snapshot.installedHash }
|
|
99
|
+
: hook)
|
|
100
|
+
: [...current.gitHooks, snapshot];
|
|
101
|
+
return { ...current, gitHooks };
|
|
102
|
+
});
|
|
103
|
+
const remove = async () => {
|
|
104
|
+
const result = await fromPromise(unlink(receiptPath()));
|
|
105
|
+
if (!result.ok && result.error.code !== "ENOENT")
|
|
106
|
+
return result;
|
|
107
|
+
return ok(undefined);
|
|
108
|
+
};
|
|
109
|
+
const installReceipt = {
|
|
110
|
+
path: receiptPath,
|
|
111
|
+
read,
|
|
112
|
+
recordShellProfile: (path) => update((current) => ({
|
|
113
|
+
...current,
|
|
114
|
+
shellProfiles: [...new Set([...current.shellProfiles, path])],
|
|
115
|
+
})),
|
|
116
|
+
recordClaudeSettings,
|
|
117
|
+
recordCodexFiles,
|
|
118
|
+
recordGitHook,
|
|
119
|
+
recordStatePath: (path) => update((current) => ({
|
|
120
|
+
...current,
|
|
121
|
+
statePaths: [...new Set([...current.statePaths, path])],
|
|
122
|
+
})),
|
|
123
|
+
remove,
|
|
124
|
+
};
|
|
125
|
+
export { installReceipt };
|
|
126
|
+
//# sourceMappingURL=install-receipt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-receipt.js","sourceRoot":"","sources":["../../src/_utils/install-receipt.ts"],"names":[],"mappings":"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"}
|