codiedev 0.10.0-beta.4 → 0.10.0-beta.5

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.
Files changed (146) hide show
  1. package/README.md +7 -1
  2. package/assets/tui-brand-plugin.tsx +14 -2
  3. package/dist/backup/cache.js +1 -5
  4. package/dist/backup/match.js +0 -6
  5. package/dist/backup/run.js +3 -35
  6. package/dist/captureExclusions.js +0 -12
  7. package/dist/captureLog.js +0 -28
  8. package/dist/captureReadiness.js +0 -58
  9. package/dist/captureSignals.js +66 -3
  10. package/dist/cli.js +41 -18
  11. package/dist/codexHookTrust.js +61 -5
  12. package/dist/codexLimitScan.js +2 -109
  13. package/dist/codie.js +27 -40
  14. package/dist/codieBrandInstall.js +0 -18
  15. package/dist/codieLauncher.js +2 -70
  16. package/dist/codieRuntime.js +19 -23
  17. package/dist/codieRuntimeInstall.js +108 -23
  18. package/dist/codieStartup.js +0 -3
  19. package/dist/codieUsage.js +38 -41
  20. package/dist/commands/ask.js +0 -3
  21. package/dist/commands/capture.js +0 -2
  22. package/dist/commands/createTicket.js +0 -10
  23. package/dist/commands/doctor.js +41 -82
  24. package/dist/commands/inbox.js +0 -2
  25. package/dist/commands/library.js +0 -3
  26. package/dist/commands/pack.js +573 -0
  27. package/dist/commands/ping.js +0 -2
  28. package/dist/commands/pull.js +6 -10
  29. package/dist/commands/push.js +2 -12
  30. package/dist/commands/react.js +0 -2
  31. package/dist/commands/reverseTicket.js +0 -33
  32. package/dist/commands/search.js +0 -4
  33. package/dist/commands/send.js +0 -5
  34. package/dist/commands/share.js +0 -4
  35. package/dist/commands/shared.js +0 -35
  36. package/dist/commands/traces.js +280 -0
  37. package/dist/configDir.js +0 -10
  38. package/dist/connect.js +21 -77
  39. package/dist/connectFlow.js +0 -9
  40. package/dist/copilotHooks.js +395 -0
  41. package/dist/copilotInstallation.js +64 -0
  42. package/dist/cursorHooks.js +40 -17
  43. package/dist/cursorLifecycle.js +109 -0
  44. package/dist/detection.js +0 -30
  45. package/dist/harnessDirs.js +73 -0
  46. package/dist/hook.js +193 -316
  47. package/dist/inboxFormat.js +0 -24
  48. package/dist/launchContext.js +150 -0
  49. package/dist/launcher.js +140 -0
  50. package/dist/limitEvent.js +41 -35
  51. package/dist/limitEventReporter.js +1 -1
  52. package/dist/mcp.js +3 -77
  53. package/dist/nativeSteering.js +24 -0
  54. package/dist/packs/codie.js +182 -0
  55. package/dist/packs/harnesses.js +374 -0
  56. package/dist/packs/hookGate.js +256 -0
  57. package/dist/packs/install.js +285 -0
  58. package/dist/packs/manifest.js +126 -0
  59. package/dist/packs/paths.js +81 -0
  60. package/dist/packs/shim.js +214 -0
  61. package/dist/packs/store.js +155 -0
  62. package/dist/packs/sync.js +170 -0
  63. package/dist/prUrl.js +0 -5
  64. package/dist/repoResolver.js +0 -19
  65. package/dist/secret.js +0 -3
  66. package/dist/security.js +0 -20
  67. package/dist/securityDeepScan.js +1 -14
  68. package/dist/securityDoctor.js +0 -2
  69. package/dist/securityFeature.js +0 -1
  70. package/dist/securityInstall.js +6 -13
  71. package/dist/securityInventory.js +23 -13
  72. package/dist/securityPilot.js +0 -2
  73. package/dist/securityPolicy.js +0 -7
  74. package/dist/selfUpdate.js +331 -0
  75. package/dist/skillMarker.js +23 -0
  76. package/dist/subagents.js +135 -0
  77. package/dist/teamSkillContext.js +10 -0
  78. package/dist/transcriptModels.js +6 -8
  79. package/dist/upgradeNudge.js +0 -30
  80. package/dist/utils.js +286 -733
  81. package/dist/version.js +0 -10
  82. package/dist/versionCheck.js +0 -33
  83. package/package.json +7 -6
  84. package/dist/backup/cache.d.ts +0 -14
  85. package/dist/backup/match.d.ts +0 -2
  86. package/dist/backup/run.d.ts +0 -25
  87. package/dist/captureExclusions.d.ts +0 -30
  88. package/dist/captureLog.d.ts +0 -20
  89. package/dist/captureReadiness.d.ts +0 -65
  90. package/dist/captureSignals.d.ts +0 -19
  91. package/dist/cli.d.ts +0 -16
  92. package/dist/codexHookTrust.d.ts +0 -34
  93. package/dist/codexLimitScan.d.ts +0 -64
  94. package/dist/codie.d.ts +0 -2
  95. package/dist/codieBrandInstall.d.ts +0 -11
  96. package/dist/codieLauncher.d.ts +0 -86
  97. package/dist/codieRuntime.d.ts +0 -29
  98. package/dist/codieRuntimeInstall.d.ts +0 -28
  99. package/dist/codieStartup.d.ts +0 -26
  100. package/dist/codieUsage.d.ts +0 -57
  101. package/dist/commands/ask.d.ts +0 -1
  102. package/dist/commands/capture.d.ts +0 -14
  103. package/dist/commands/createTicket.d.ts +0 -27
  104. package/dist/commands/delete.d.ts +0 -1
  105. package/dist/commands/doctor.d.ts +0 -1
  106. package/dist/commands/inbox.d.ts +0 -3
  107. package/dist/commands/library.d.ts +0 -2
  108. package/dist/commands/note.d.ts +0 -1
  109. package/dist/commands/ping.d.ts +0 -1
  110. package/dist/commands/promote.d.ts +0 -1
  111. package/dist/commands/pull.d.ts +0 -2
  112. package/dist/commands/push.d.ts +0 -33
  113. package/dist/commands/react.d.ts +0 -2
  114. package/dist/commands/reverseTicket.d.ts +0 -2
  115. package/dist/commands/search.d.ts +0 -2
  116. package/dist/commands/security.d.ts +0 -1
  117. package/dist/commands/send.d.ts +0 -2
  118. package/dist/commands/share.d.ts +0 -2
  119. package/dist/commands/shared.d.ts +0 -64
  120. package/dist/configDir.d.ts +0 -1
  121. package/dist/connect.d.ts +0 -1
  122. package/dist/connectFlow.d.ts +0 -13
  123. package/dist/cursorHooks.d.ts +0 -23
  124. package/dist/detection.d.ts +0 -30
  125. package/dist/hook.d.ts +0 -6
  126. package/dist/inboxFormat.d.ts +0 -38
  127. package/dist/limitEvent.d.ts +0 -16
  128. package/dist/limitEventReporter.d.ts +0 -21
  129. package/dist/mcp.d.ts +0 -12
  130. package/dist/prUrl.d.ts +0 -9
  131. package/dist/repoResolver.d.ts +0 -17
  132. package/dist/secret.d.ts +0 -1
  133. package/dist/security.d.ts +0 -102
  134. package/dist/securityDeepScan.d.ts +0 -41
  135. package/dist/securityDoctor.d.ts +0 -32
  136. package/dist/securityFeature.d.ts +0 -5
  137. package/dist/securityInstall.d.ts +0 -63
  138. package/dist/securityInventory.d.ts +0 -54
  139. package/dist/securityPilot.d.ts +0 -19
  140. package/dist/securityPolicy.d.ts +0 -33
  141. package/dist/securitySession.d.ts +0 -6
  142. package/dist/transcriptModels.d.ts +0 -18
  143. package/dist/upgradeNudge.d.ts +0 -25
  144. package/dist/utils.d.ts +0 -346
  145. package/dist/version.d.ts +0 -1
  146. package/dist/versionCheck.d.ts +0 -68
@@ -0,0 +1,374 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ADAPTERS = exports.codieAdapter = exports.cursorAdapter = exports.CURSOR_MARKER = exports.codexAdapter = exports.copilotAdapter = exports.claudeAdapter = exports.HARNESSES = void 0;
37
+ exports.defaultRunner = defaultRunner;
38
+ exports.onPath = onPath;
39
+ exports.copyCursorSkills = copyCursorSkills;
40
+ exports.removeCursorSkills = removeCursorSkills;
41
+ exports.cursorLocalPluginsDir = cursorLocalPluginsDir;
42
+ exports.cursorPluginDir = cursorPluginDir;
43
+ exports.installCursorPlugin = installCursorPlugin;
44
+ exports.removeCursorPlugin = removeCursorPlugin;
45
+ exports.parseHarnessList = parseHarnessList;
46
+ const fs = __importStar(require("fs"));
47
+ const path = __importStar(require("path"));
48
+ const child_process_1 = require("child_process");
49
+ const harnessDirs_1 = require("../harnessDirs");
50
+ const paths_1 = require("./paths");
51
+ exports.HARNESSES = ["claude", "copilot", "codex", "cursor", "codie"];
52
+ function defaultRunner(env) {
53
+ return (command, args, options = {}) => {
54
+ const result = (0, child_process_1.spawnSync)(command, args, {
55
+ encoding: "utf8",
56
+ env,
57
+ cwd: options.cwd,
58
+ timeout: 180_000,
59
+ stdio: ["ignore", "pipe", "pipe"],
60
+ });
61
+ return {
62
+ status: result.status,
63
+ stdout: result.stdout ?? "",
64
+ stderr: result.stderr ?? "",
65
+ ...(result.error ? { error: result.error.message } : {}),
66
+ };
67
+ };
68
+ }
69
+ function onPath(bin, env) {
70
+ const dirs = (env.PATH ?? "").split(path.delimiter).filter(Boolean);
71
+ const exts = process.platform === "win32" ? (env.PATHEXT ?? ".EXE;.CMD;.BAT").split(";") : [""];
72
+ for (const dir of dirs) {
73
+ for (const ext of exts) {
74
+ const candidate = path.join(dir, bin + ext);
75
+ try {
76
+ const stat = fs.statSync(candidate);
77
+ if (stat.isFile()) {
78
+ if (process.platform === "win32")
79
+ return true;
80
+ fs.accessSync(candidate, fs.constants.X_OK);
81
+ return true;
82
+ }
83
+ }
84
+ catch {
85
+ }
86
+ }
87
+ }
88
+ return false;
89
+ }
90
+ function uninstallRef(slug) {
91
+ return `${slug}@${paths_1.MARKETPLACE_NAME}`;
92
+ }
93
+ function uninstallWith(ctx, bin, verb) {
94
+ const result = ctx.run(bin, ["plugin", verb, uninstallRef(ctx.slug)]);
95
+ if (result.status === 0)
96
+ return "uninstalled";
97
+ if (/not (found|installed)/i.test(`${result.stdout}\n${result.stderr}`))
98
+ return "already removed";
99
+ throw new Error(`\`${bin} plugin ${verb} ${uninstallRef(ctx.slug)}\` failed (${describe(result)})`);
100
+ }
101
+ function describe(result) {
102
+ if (result.error)
103
+ return result.error;
104
+ const text = (result.stderr || result.stdout || "").trim().split("\n").filter(Boolean).pop();
105
+ return text ? `exit ${result.status}: ${text.slice(0, 200)}` : `exit ${result.status}`;
106
+ }
107
+ function must(ctx, bin, args, options) {
108
+ const result = ctx.run(bin, args, options);
109
+ if (result.status !== 0)
110
+ throw new Error(`\`${bin} ${args.join(" ")}\` failed (${describe(result)})`);
111
+ return result;
112
+ }
113
+ function alreadyExists(result) {
114
+ return /already|exists/i.test(`${result.stdout}\n${result.stderr}`);
115
+ }
116
+ function wasInstalled(ctx, harness) {
117
+ return Boolean(ctx.previous?.harnesses?.includes(harness));
118
+ }
119
+ function contentChangedInPlace(ctx) {
120
+ const prev = ctx.previous;
121
+ return Boolean(prev && prev.version === ctx.manifest.version && prev.contentHash !== ctx.manifest.contentHash);
122
+ }
123
+ function pluginRef(ctx) {
124
+ return `${ctx.manifest.slug}@${paths_1.MARKETPLACE_NAME}`;
125
+ }
126
+ function claudeMarketplaceKnown(env, home) {
127
+ try {
128
+ const known = JSON.parse(fs.readFileSync(path.join((0, harnessDirs_1.claudeConfigDir)(env, home), "plugins", "known_marketplaces.json"), "utf8"));
129
+ return Boolean(known && typeof known === "object" && paths_1.MARKETPLACE_NAME in known);
130
+ }
131
+ catch {
132
+ return false;
133
+ }
134
+ }
135
+ function ensurePortableMarketplace(ctx, bin) {
136
+ const root = (0, paths_1.portableRoot)(ctx.root);
137
+ const stamp = path.join(root, `.registered-${bin}`);
138
+ if (!fs.existsSync(stamp))
139
+ ctx.run(bin, ["plugin", "marketplace", "remove", paths_1.MARKETPLACE_NAME]);
140
+ const added = ctx.run(bin, ["plugin", "marketplace", "add", root]);
141
+ if (added.status !== 0 && !alreadyExists(added)) {
142
+ throw new Error(`\`${bin} plugin marketplace add\` failed (${describe(added)})`);
143
+ }
144
+ fs.writeFileSync(stamp, `${root}\n`);
145
+ }
146
+ function marketplaceInstall(ctx, bin, harness, verbs, marketplaceKnown, portable = false) {
147
+ if (portable) {
148
+ ensurePortableMarketplace(ctx, bin);
149
+ }
150
+ else if (marketplaceKnown) {
151
+ ctx.run(bin, ["plugin", "marketplace", "update", paths_1.MARKETPLACE_NAME]);
152
+ }
153
+ else {
154
+ const added = ctx.run(bin, ["plugin", "marketplace", "add", ctx.root]);
155
+ if (added.status !== 0 && !alreadyExists(added)) {
156
+ throw new Error(`\`${bin} plugin marketplace add\` failed (${describe(added)})`);
157
+ }
158
+ if (added.status !== 0)
159
+ ctx.run(bin, ["plugin", "marketplace", "update", paths_1.MARKETPLACE_NAME]);
160
+ }
161
+ const ref = pluginRef(ctx);
162
+ if (wasInstalled(ctx, harness)) {
163
+ if (contentChangedInPlace(ctx)) {
164
+ ctx.run(bin, ["plugin", verbs.uninstall, ref]);
165
+ must(ctx, bin, ["plugin", verbs.install, ref]);
166
+ return "reinstalled";
167
+ }
168
+ const updated = ctx.run(bin, ["plugin", verbs.update, ref]);
169
+ if (updated.status === 0)
170
+ return "updated";
171
+ }
172
+ const installed = ctx.run(bin, ["plugin", verbs.install, ref]);
173
+ if (installed.status === 0)
174
+ return "installed";
175
+ if (alreadyExists(installed)) {
176
+ must(ctx, bin, ["plugin", verbs.update, ref]);
177
+ return "updated";
178
+ }
179
+ throw new Error(`\`${bin} plugin ${verbs.install} ${ref}\` failed (${describe(installed)})`);
180
+ }
181
+ exports.claudeAdapter = {
182
+ name: "claude",
183
+ detect: (ctx) => onPath("claude", ctx.env),
184
+ install: (ctx) => marketplaceInstall(ctx, "claude", "claude", { install: "install", update: "update", uninstall: "uninstall" }, claudeMarketplaceKnown(ctx.env, ctx.home)),
185
+ plan: (ctx) => `claude plugin marketplace add ${ctx.root}; claude plugin install ${pluginRef(ctx)}`,
186
+ uninstall: (ctx) => uninstallWith(ctx, "claude", "uninstall"),
187
+ };
188
+ exports.copilotAdapter = {
189
+ name: "copilot",
190
+ detect: (ctx) => onPath("copilot", ctx.env),
191
+ install: (ctx) => marketplaceInstall(ctx, "copilot", "copilot", { install: "install", update: "update", uninstall: "uninstall" }, false, true),
192
+ plan: (ctx) => `copilot plugin marketplace add ${(0, paths_1.portableRoot)(ctx.root)}; copilot plugin install ${pluginRef(ctx)}`,
193
+ uninstall: (ctx) => uninstallWith(ctx, "copilot", "uninstall"),
194
+ };
195
+ exports.codexAdapter = {
196
+ name: "codex",
197
+ detect: (ctx) => onPath("codex", ctx.env),
198
+ install: (ctx) => {
199
+ ensurePortableMarketplace(ctx, "codex");
200
+ const ref = pluginRef(ctx);
201
+ const reinstall = wasInstalled(ctx, "codex");
202
+ if (reinstall)
203
+ ctx.run("codex", ["plugin", "remove", ref]);
204
+ must(ctx, "codex", ["plugin", "add", ref]);
205
+ return reinstall ? "reinstalled" : "installed";
206
+ },
207
+ plan: (ctx) => `codex plugin marketplace add ${(0, paths_1.portableRoot)(ctx.root)}; codex plugin add ${pluginRef(ctx)}; trust pack hooks in config.toml`,
208
+ uninstall: (ctx) => uninstallWith(ctx, "codex", "remove"),
209
+ };
210
+ exports.CURSOR_MARKER = ".codiedev-pack";
211
+ function cursorSkillsDir(home) {
212
+ return path.join(home, ".cursor", "skills");
213
+ }
214
+ function copyCursorSkills(home, manifest, pluginDirPath) {
215
+ const base = cursorSkillsDir(home);
216
+ fs.mkdirSync(base, { recursive: true });
217
+ const notes = [];
218
+ const wanted = new Set(manifest.skills.map((s) => s.name));
219
+ for (const entry of fs.readdirSync(base)) {
220
+ const marker = path.join(base, entry, exports.CURSOR_MARKER);
221
+ try {
222
+ if (fs.readFileSync(marker, "utf8").trim() === manifest.slug && !wanted.has(entry)) {
223
+ fs.rmSync(path.join(base, entry), { recursive: true, force: true });
224
+ }
225
+ }
226
+ catch {
227
+ }
228
+ }
229
+ for (const skill of manifest.skills) {
230
+ const dest = path.join(base, skill.name);
231
+ if (fs.existsSync(dest)) {
232
+ let owner = "";
233
+ try {
234
+ owner = fs.readFileSync(path.join(dest, exports.CURSOR_MARKER), "utf8").trim();
235
+ }
236
+ catch {
237
+ owner = "";
238
+ }
239
+ if (owner !== manifest.slug) {
240
+ notes.push(`kept existing ~/.cursor/skills/${skill.name}`);
241
+ continue;
242
+ }
243
+ fs.rmSync(dest, { recursive: true, force: true });
244
+ }
245
+ fs.mkdirSync(dest, { recursive: true });
246
+ fs.copyFileSync(path.join(pluginDirPath, "skills", skill.name, "SKILL.md"), path.join(dest, "SKILL.md"));
247
+ fs.writeFileSync(path.join(dest, exports.CURSOR_MARKER), `${manifest.slug}\n`);
248
+ }
249
+ return notes;
250
+ }
251
+ function removeCursorSkills(home, slug) {
252
+ const base = cursorSkillsDir(home);
253
+ let removed = 0;
254
+ let entries = [];
255
+ try {
256
+ entries = fs.readdirSync(base);
257
+ }
258
+ catch {
259
+ return 0;
260
+ }
261
+ for (const entry of entries) {
262
+ try {
263
+ if (fs.readFileSync(path.join(base, entry, exports.CURSOR_MARKER), "utf8").trim() === slug) {
264
+ fs.rmSync(path.join(base, entry), { recursive: true, force: true });
265
+ removed += 1;
266
+ }
267
+ }
268
+ catch {
269
+ }
270
+ }
271
+ return removed;
272
+ }
273
+ function cursorLocalPluginsDir(home) {
274
+ return path.join(home, ".cursor", "plugins", "local");
275
+ }
276
+ function cursorPluginDir(home, slug) {
277
+ return path.join(cursorLocalPluginsDir(home), `codiedev-${slug}`);
278
+ }
279
+ function markerOwner(dir) {
280
+ try {
281
+ return fs.readFileSync(path.join(dir, exports.CURSOR_MARKER), "utf8").trim();
282
+ }
283
+ catch {
284
+ return null;
285
+ }
286
+ }
287
+ function copyTreeNoSymlinks(source, dest, depth = 0) {
288
+ if (depth > 32)
289
+ throw new Error(`plugin tree too deep at ${source}`);
290
+ fs.mkdirSync(dest, { recursive: true });
291
+ for (const entry of fs.readdirSync(source)) {
292
+ const from = path.join(source, entry);
293
+ const to = path.join(dest, entry);
294
+ const stat = fs.statSync(from);
295
+ if (stat.isDirectory())
296
+ copyTreeNoSymlinks(from, to, depth + 1);
297
+ else if (stat.isFile())
298
+ fs.writeFileSync(to, fs.readFileSync(from));
299
+ }
300
+ }
301
+ function installCursorPlugin(home, slug, sourceDir) {
302
+ const parent = cursorLocalPluginsDir(home);
303
+ const target = cursorPluginDir(home, slug);
304
+ if (fs.existsSync(target) && markerOwner(target) !== slug) {
305
+ throw new Error(`${target} exists and wasn't written by Codiedev; leaving it alone`);
306
+ }
307
+ fs.mkdirSync(parent, { recursive: true });
308
+ const stamp = `${process.pid}-${Date.now()}`;
309
+ const tmp = path.join(parent, `.codiedev-${slug}.tmp-${stamp}`);
310
+ const old = path.join(parent, `.codiedev-${slug}.old-${stamp}`);
311
+ try {
312
+ copyTreeNoSymlinks(sourceDir, tmp);
313
+ fs.writeFileSync(path.join(tmp, exports.CURSOR_MARKER), `${slug}\n`);
314
+ if (fs.existsSync(target))
315
+ fs.renameSync(target, old);
316
+ fs.renameSync(tmp, target);
317
+ }
318
+ catch (error) {
319
+ fs.rmSync(tmp, { recursive: true, force: true });
320
+ if (!fs.existsSync(target) && fs.existsSync(old))
321
+ fs.renameSync(old, target);
322
+ throw error;
323
+ }
324
+ fs.rmSync(old, { recursive: true, force: true });
325
+ return target;
326
+ }
327
+ function removeCursorPlugin(home, slug) {
328
+ const target = cursorPluginDir(home, slug);
329
+ if (markerOwner(target) !== slug)
330
+ return false;
331
+ fs.rmSync(target, { recursive: true, force: true });
332
+ return true;
333
+ }
334
+ exports.cursorAdapter = {
335
+ name: "cursor",
336
+ detect: (ctx) => onPath("cursor-agent", ctx.env) || fs.existsSync(path.join(ctx.home, ".cursor")),
337
+ install: (ctx) => {
338
+ try {
339
+ installCursorPlugin(ctx.home, ctx.manifest.slug, ctx.portablePluginDir);
340
+ }
341
+ catch (error) {
342
+ const notes = copyCursorSkills(ctx.home, ctx.manifest, ctx.portablePluginDir);
343
+ const reason = error instanceof Error ? error.message : String(error);
344
+ return [`skills only (couldn't write ~/.cursor/plugins/local: ${reason})`, ...notes].join("; ");
345
+ }
346
+ const migrated = removeCursorSkills(ctx.home, ctx.manifest.slug);
347
+ return migrated ? `installed (removed ${migrated} old ~/.cursor/skills cop${migrated === 1 ? "y" : "ies"})` : "installed";
348
+ },
349
+ plan: (ctx) => `copy plugin to ${cursorPluginDir(ctx.home, ctx.manifest.slug)}`,
350
+ uninstall: (ctx) => {
351
+ const plugin = removeCursorPlugin(ctx.home, ctx.slug);
352
+ const skills = removeCursorSkills(ctx.home, ctx.slug);
353
+ if (!plugin && !skills)
354
+ return "already removed";
355
+ return skills ? `uninstalled (${skills} copied skill${skills === 1 ? "" : "s"} removed)` : "uninstalled";
356
+ },
357
+ };
358
+ exports.codieAdapter = {
359
+ name: "codie",
360
+ detect: () => true,
361
+ install: () => "loads on next `codie` launch",
362
+ plan: () => "inject skills/agents/hook shim at next codie launch",
363
+ uninstall: () => "removed from next `codie` launch",
364
+ };
365
+ exports.ADAPTERS = [exports.claudeAdapter, exports.copilotAdapter, exports.codexAdapter, exports.cursorAdapter, exports.codieAdapter];
366
+ function parseHarnessList(value) {
367
+ if (value === undefined)
368
+ return undefined;
369
+ const names = value.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
370
+ const unknown = names.filter((n) => !exports.HARNESSES.includes(n));
371
+ if (unknown.length)
372
+ throw new Error(`Unknown harness: ${unknown.join(", ")} (valid: ${exports.HARNESSES.join(", ")})`);
373
+ return [...new Set(names)];
374
+ }
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MAX_GATED_COMMAND_BYTES = void 0;
37
+ exports.skillsFromPayload = skillsFromPayload;
38
+ exports.encodeGatedCommand = encodeGatedCommand;
39
+ exports.decodeGatedCommand = decodeGatedCommand;
40
+ exports.parseGateArgs = parseGateArgs;
41
+ exports.gateMatches = gateMatches;
42
+ exports.splitShellOverride = splitShellOverride;
43
+ exports.planShellCommand = planShellCommand;
44
+ exports.planGateCommand = planGateCommand;
45
+ exports.runHookGate = runHookGate;
46
+ exports.runHookGateCli = runHookGateCli;
47
+ const fs = __importStar(require("fs"));
48
+ const path = __importStar(require("path"));
49
+ const child_process_1 = require("child_process");
50
+ function str(value) {
51
+ return typeof value === "string" && value ? value : undefined;
52
+ }
53
+ function parseMaybeJson(value) {
54
+ if (typeof value !== "string")
55
+ return value;
56
+ try {
57
+ return JSON.parse(value);
58
+ }
59
+ catch {
60
+ return value;
61
+ }
62
+ }
63
+ const SKILL_PATH = /[\\/]skills[\\/]([^\\/\s'"`;|&<>()]+)[\\/]SKILL\.md\b/g;
64
+ function skillsInPath(text) {
65
+ return [...text.matchAll(SKILL_PATH)].map((m) => m[1]);
66
+ }
67
+ function stripPlugin(name) {
68
+ const index = name.lastIndexOf(":");
69
+ return index >= 0 ? name.slice(index + 1) : name;
70
+ }
71
+ function skillsFromPayload(payload) {
72
+ if (!payload || typeof payload !== "object" || Array.isArray(payload))
73
+ return [];
74
+ const p = payload;
75
+ const toolName = str(p.tool_name) ?? str(p.toolName) ?? "";
76
+ const rawInput = parseMaybeJson(p.tool_input ?? p.toolInput ?? p.toolArgs ?? p.input);
77
+ const input = rawInput && typeof rawInput === "object" && !Array.isArray(rawInput)
78
+ ? rawInput
79
+ : {};
80
+ const tool = toolName.toLowerCase();
81
+ if (tool === "skill") {
82
+ const name = str(input.skill) ?? str(input.name) ?? str(input.skill_name);
83
+ return name ? [stripPlugin(name.trim())] : [];
84
+ }
85
+ if (tool === "read" || tool === "view" || tool === "read_file") {
86
+ const file = str(input.file_path) ?? str(input.path) ?? str(input.filePath) ?? "";
87
+ return skillsInPath(file);
88
+ }
89
+ if (tool === "bash" || tool === "shell" || tool === "exec_command" || tool === "local_shell") {
90
+ const command = Array.isArray(input.command) ? input.command.join(" ") : str(input.command) ?? str(input.cmd) ?? "";
91
+ return skillsInPath(command);
92
+ }
93
+ return [];
94
+ }
95
+ exports.MAX_GATED_COMMAND_BYTES = 16 * 1024;
96
+ function encodeGatedCommand(command) {
97
+ return Buffer.from(command, "utf8").toString("base64url");
98
+ }
99
+ function decodeGatedCommand(value) {
100
+ if (!/^[A-Za-z0-9_-]+$/.test(value) || value.length % 4 === 1)
101
+ throw new Error("--cmd-b64 is not base64url");
102
+ if (value.length > Math.ceil((exports.MAX_GATED_COMMAND_BYTES * 4) / 3) + 4)
103
+ throw new Error("--cmd-b64 command is over 16KB");
104
+ const bytes = Buffer.from(value, "base64url");
105
+ if (bytes.toString("base64url") !== value)
106
+ throw new Error("--cmd-b64 is not canonical base64url");
107
+ if (bytes.length > exports.MAX_GATED_COMMAND_BYTES)
108
+ throw new Error("--cmd-b64 command is over 16KB");
109
+ let text;
110
+ try {
111
+ text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
112
+ }
113
+ catch {
114
+ throw new Error("--cmd-b64 command is not UTF-8");
115
+ }
116
+ if (text.includes("\u0000"))
117
+ throw new Error("--cmd-b64 command contains NUL");
118
+ if (!text.trim())
119
+ throw new Error("--cmd-b64 command is empty");
120
+ return text;
121
+ }
122
+ function parseGateArgs(argv) {
123
+ const sep = argv.indexOf("--");
124
+ const flags = sep >= 0 ? argv.slice(0, sep) : argv;
125
+ const command = sep >= 0 ? argv.slice(sep + 1) : [];
126
+ let skills = [];
127
+ let cmdB64;
128
+ for (let i = 0; i < flags.length; i++) {
129
+ const a = flags[i];
130
+ if (a === "--cmd-b64" || a.startsWith("--cmd-b64=")) {
131
+ cmdB64 = a === "--cmd-b64" ? flags[++i] ?? "" : a.slice("--cmd-b64=".length);
132
+ continue;
133
+ }
134
+ const value = a === "--skills" || a === "--skill" ? flags[++i] : a.startsWith("--skills=") ? a.slice(9) : undefined;
135
+ if (value === undefined)
136
+ throw new Error(`Unknown hook-gate argument: ${a}`);
137
+ skills.push(...value.split(",").map((s) => stripPlugin(s.trim())).filter(Boolean));
138
+ }
139
+ skills = [...new Set(skills)];
140
+ if (skills.length === 0)
141
+ throw new Error("hook-gate needs --skills a,b");
142
+ if (cmdB64 !== undefined && command.length)
143
+ throw new Error("hook-gate takes --cmd-b64 or -- <command>, not both");
144
+ if (cmdB64 === undefined && command.length === 0)
145
+ throw new Error("hook-gate needs --cmd-b64 <base64url> or -- <command>");
146
+ return { skills, command, ...(cmdB64 !== undefined ? { cmdB64 } : {}) };
147
+ }
148
+ function gateMatches(skills, payload) {
149
+ const running = skillsFromPayload(payload);
150
+ return running.some((name) => skills.includes(name));
151
+ }
152
+ function splitShellOverride(value) {
153
+ const out = [];
154
+ for (const m of value.matchAll(/"([^"]*)"|'([^']*)'|(\S+)/g))
155
+ out.push(m[1] ?? m[2] ?? m[3]);
156
+ return out;
157
+ }
158
+ function shellFor(line, platform, env) {
159
+ const override = env.CODIEDEV_HOOK_SHELL?.trim();
160
+ if (override) {
161
+ const [file, ...args] = splitShellOverride(override);
162
+ if (file)
163
+ return { file, args: [...args, line] };
164
+ }
165
+ if (platform === "win32") {
166
+ return { file: env.ComSpec || env.COMSPEC || "cmd.exe", args: ["/d", "/s", "/c", `"${line}"`], verbatim: true };
167
+ }
168
+ return { file: "/bin/sh", args: ["-c", line] };
169
+ }
170
+ function planShellCommand(line, options = {}) {
171
+ return shellFor(line, options.platform ?? process.platform, options.env ?? process.env);
172
+ }
173
+ function planGateCommand(command, options = {}) {
174
+ const platform = options.platform ?? process.platform;
175
+ const env = options.env ?? process.env;
176
+ const legacy = command.length === 3 && /^(?:\/bin\/)?sh(?:\.exe)?$/i.test(command[0]) && command[1] === "-c";
177
+ if (legacy && platform === "win32" && !(options.hasSh ?? (() => onPathSimple("sh", env, platform)))()) {
178
+ return { ...shellFor(command[2], platform, env), note: "codiedev hook-gate: sh isn't available; running the hook with cmd.exe instead\n" };
179
+ }
180
+ const [file, ...args] = command;
181
+ return { file, args };
182
+ }
183
+ function onPathSimple(bin, env, platform) {
184
+ const sep = platform === "win32" ? ";" : ":";
185
+ const exts = platform === "win32" ? (env.PATHEXT ?? ".EXE;.CMD;.BAT").split(";") : [""];
186
+ for (const dir of (env.PATH ?? env.Path ?? "").split(sep).filter(Boolean)) {
187
+ for (const ext of exts) {
188
+ try {
189
+ if (fs.statSync(path.join(dir, bin + ext)).isFile())
190
+ return true;
191
+ }
192
+ catch {
193
+ }
194
+ }
195
+ }
196
+ return false;
197
+ }
198
+ function runHookGate(argv, stdin, env = process.env, options = {}) {
199
+ let args;
200
+ try {
201
+ args = parseGateArgs(argv);
202
+ }
203
+ catch (error) {
204
+ process.stderr.write(`codiedev hook-gate: ${error.message}\n`);
205
+ return 0;
206
+ }
207
+ let payload;
208
+ try {
209
+ payload = JSON.parse(stdin);
210
+ }
211
+ catch {
212
+ return 0;
213
+ }
214
+ if (!gateMatches(args.skills, payload))
215
+ return 0;
216
+ let plan;
217
+ if (args.cmdB64 !== undefined) {
218
+ let line;
219
+ try {
220
+ line = decodeGatedCommand(args.cmdB64);
221
+ }
222
+ catch (error) {
223
+ process.stderr.write(`codiedev hook-gate: ${error.message}; hook skipped\n`);
224
+ return 0;
225
+ }
226
+ plan = planShellCommand(line, { ...options, env });
227
+ }
228
+ else {
229
+ plan = planGateCommand(args.command, { ...options, env });
230
+ }
231
+ if (plan.note)
232
+ process.stderr.write(plan.note);
233
+ const result = (options.spawn ?? child_process_1.spawnSync)(plan.file, plan.args, {
234
+ input: stdin,
235
+ stdio: ["pipe", "inherit", "inherit"],
236
+ env,
237
+ windowsHide: true,
238
+ ...(plan.verbatim ? { windowsVerbatimArguments: true } : {}),
239
+ });
240
+ const ignoredStdin = result.error?.code === "EPIPE" && result.status !== null;
241
+ if (result.error && !ignoredStdin) {
242
+ process.stderr.write(`codiedev hook-gate: ${result.error.message}\n`);
243
+ return 1;
244
+ }
245
+ return result.status ?? 1;
246
+ }
247
+ function runHookGateCli(argv) {
248
+ let stdin = "";
249
+ try {
250
+ stdin = fs.readFileSync(0, "utf8");
251
+ }
252
+ catch {
253
+ stdin = "";
254
+ }
255
+ process.exitCode = runHookGate(argv, stdin);
256
+ }