codiedev 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/doctor.js +10 -5
- package/dist/utils.js +55 -38
- package/package.json +1 -1
package/dist/commands/doctor.js
CHANGED
|
@@ -76,6 +76,14 @@ function hasCursorMcpEntry() {
|
|
|
76
76
|
return false;
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
+
// Match both legacy `npx codiedev-hook ...` and absolute-path forms
|
|
80
|
+
// `<node> <.../codiedev/dist/hook.js> ...` — installer switched to absolute
|
|
81
|
+
// paths in 0.6.1 to work in GUI-launched contexts where shell PATH is missing.
|
|
82
|
+
function isCodiedevHookCommand(cmd) {
|
|
83
|
+
if (!cmd)
|
|
84
|
+
return false;
|
|
85
|
+
return cmd.includes("codiedev-hook") || /codiedev[\\/]dist[\\/]hook/.test(cmd);
|
|
86
|
+
}
|
|
79
87
|
// Cursor's hooks.json schema is { hooks: { sessionEnd: [{ command, ... }] } }
|
|
80
88
|
// — flat array of objects with `command`, not the Claude/Codex nested
|
|
81
89
|
// `{ hooks: [{ command }] }` wrapper.
|
|
@@ -88,10 +96,7 @@ function hasCursorHook() {
|
|
|
88
96
|
const arr = parsed.hooks?.sessionEnd;
|
|
89
97
|
if (!Array.isArray(arr))
|
|
90
98
|
return false;
|
|
91
|
-
return arr.some((h) =>
|
|
92
|
-
const cmd = h.command;
|
|
93
|
-
return (cmd ?? "").includes("codiedev-hook");
|
|
94
|
-
});
|
|
99
|
+
return arr.some((h) => isCodiedevHookCommand(h.command));
|
|
95
100
|
}
|
|
96
101
|
catch {
|
|
97
102
|
return false;
|
|
@@ -110,7 +115,7 @@ function hasCodiedevHook(settingsPath, hookKey) {
|
|
|
110
115
|
const inner = h.hooks;
|
|
111
116
|
if (!Array.isArray(inner))
|
|
112
117
|
return false;
|
|
113
|
-
return inner.some((x) => (x.command
|
|
118
|
+
return inner.some((x) => isCodiedevHookCommand(x.command));
|
|
114
119
|
});
|
|
115
120
|
}
|
|
116
121
|
catch {
|
package/dist/utils.js
CHANGED
|
@@ -142,6 +142,36 @@ const CURSOR_HOOKS_PATH = path.join(CURSOR_DIR, "hooks.json");
|
|
|
142
142
|
const CURSOR_MCP_PATH = path.join(CURSOR_DIR, "mcp.json");
|
|
143
143
|
const CURSOR_RULES_DIR = path.join(CURSOR_DIR, "rules");
|
|
144
144
|
const CURSOR_RULES_PATH = path.join(CURSOR_RULES_DIR, "codiedev.mdc");
|
|
145
|
+
// GUI-launched agents (Cursor.app, future JetBrains plugins) don't source the
|
|
146
|
+
// user's shell rc, so nvm-managed `npx` and `node` aren't on PATH. Resolve the
|
|
147
|
+
// absolute path to the current node binary and our hook.js at install time and
|
|
148
|
+
// write that into hook configs so execution doesn't depend on the spawned
|
|
149
|
+
// shell's PATH. Falls back to `npx` if we can't resolve dist/hook.js.
|
|
150
|
+
function shellQuote(s) {
|
|
151
|
+
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
152
|
+
}
|
|
153
|
+
function resolveHookCommand(subcommand) {
|
|
154
|
+
try {
|
|
155
|
+
const cliEntry = process.argv[1];
|
|
156
|
+
if (cliEntry) {
|
|
157
|
+
const realCli = fs.realpathSync(cliEntry);
|
|
158
|
+
const distDir = path.dirname(realCli);
|
|
159
|
+
const hookScript = path.join(distDir, "hook.js");
|
|
160
|
+
if (fs.existsSync(hookScript)) {
|
|
161
|
+
return `${shellQuote(process.execPath)} ${shellQuote(hookScript)} ${subcommand}`;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// Fall through to npx fallback.
|
|
167
|
+
}
|
|
168
|
+
return `npx codiedev-hook ${subcommand}`;
|
|
169
|
+
}
|
|
170
|
+
function isCodiedevHookCommand(cmd) {
|
|
171
|
+
if (!cmd)
|
|
172
|
+
return false;
|
|
173
|
+
return cmd.includes("codiedev-hook") || /codiedev[\\/]dist[\\/]hook/.test(cmd);
|
|
174
|
+
}
|
|
145
175
|
function claudeCodeInstalled() {
|
|
146
176
|
return fs.existsSync(CLAUDE_DIR);
|
|
147
177
|
}
|
|
@@ -169,30 +199,27 @@ function installHook() {
|
|
|
169
199
|
if (!hooks.SessionEnd) {
|
|
170
200
|
hooks.SessionEnd = [];
|
|
171
201
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
});
|
|
202
|
+
// Drop any prior codiedev entries (legacy `npx` form or older absolute
|
|
203
|
+
// paths) before re-adding so connect re-runs upgrade the resolved binary
|
|
204
|
+
// path instead of leaving stale entries behind.
|
|
205
|
+
const existing = hooks.SessionEnd;
|
|
206
|
+
const filtered = existing.filter((hook) => {
|
|
207
|
+
const inner = hook.hooks;
|
|
208
|
+
if (Array.isArray(inner)) {
|
|
209
|
+
return !inner.some((h) => isCodiedevHookCommand(h.command));
|
|
181
210
|
}
|
|
182
|
-
return
|
|
211
|
+
return !isCodiedevHookCommand(hook.matcher);
|
|
183
212
|
});
|
|
184
|
-
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
sessionEndHooks.push({
|
|
213
|
+
filtered.push({
|
|
188
214
|
matcher: ".*",
|
|
189
215
|
hooks: [
|
|
190
216
|
{
|
|
191
217
|
type: "command",
|
|
192
|
-
command: "
|
|
218
|
+
command: resolveHookCommand("capture"),
|
|
193
219
|
},
|
|
194
220
|
],
|
|
195
221
|
});
|
|
222
|
+
hooks.SessionEnd = filtered;
|
|
196
223
|
if (!fs.existsSync(CLAUDE_DIR)) {
|
|
197
224
|
fs.mkdirSync(CLAUDE_DIR, { recursive: true });
|
|
198
225
|
}
|
|
@@ -469,28 +496,23 @@ function installCodexHook() {
|
|
|
469
496
|
if (!hooks.Stop) {
|
|
470
497
|
hooks.Stop = [];
|
|
471
498
|
}
|
|
472
|
-
const
|
|
473
|
-
const
|
|
499
|
+
const existing = hooks.Stop;
|
|
500
|
+
const filtered = existing.filter((hook) => {
|
|
474
501
|
const inner = hook.hooks;
|
|
475
|
-
if (!inner)
|
|
476
|
-
return
|
|
477
|
-
return inner.some((h) =>
|
|
478
|
-
const cmd = h.command;
|
|
479
|
-
return cmd && cmd.includes("codiedev-hook");
|
|
480
|
-
});
|
|
502
|
+
if (!Array.isArray(inner))
|
|
503
|
+
return true;
|
|
504
|
+
return !inner.some((h) => isCodiedevHookCommand(h.command));
|
|
481
505
|
});
|
|
482
|
-
|
|
483
|
-
return;
|
|
484
|
-
}
|
|
485
|
-
stopHooks.push({
|
|
506
|
+
filtered.push({
|
|
486
507
|
hooks: [
|
|
487
508
|
{
|
|
488
509
|
type: "command",
|
|
489
|
-
command: "
|
|
510
|
+
command: resolveHookCommand("capture-codex"),
|
|
490
511
|
timeout: 30,
|
|
491
512
|
},
|
|
492
513
|
],
|
|
493
514
|
});
|
|
515
|
+
hooks.Stop = filtered;
|
|
494
516
|
if (!fs.existsSync(CODEX_DIR)) {
|
|
495
517
|
fs.mkdirSync(CODEX_DIR, { recursive: true });
|
|
496
518
|
}
|
|
@@ -524,19 +546,14 @@ function installCursorHook() {
|
|
|
524
546
|
if (!hooks.sessionEnd) {
|
|
525
547
|
hooks.sessionEnd = [];
|
|
526
548
|
}
|
|
527
|
-
const
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
});
|
|
532
|
-
if (alreadyInstalled) {
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
535
|
-
sessionEndHooks.push({
|
|
536
|
-
command: "npx codiedev-hook capture-cursor",
|
|
549
|
+
const existing = hooks.sessionEnd;
|
|
550
|
+
const filtered = existing.filter((h) => !isCodiedevHookCommand(h.command));
|
|
551
|
+
filtered.push({
|
|
552
|
+
command: resolveHookCommand("capture-cursor"),
|
|
537
553
|
type: "command",
|
|
538
554
|
timeout: 30,
|
|
539
555
|
});
|
|
556
|
+
hooks.sessionEnd = filtered;
|
|
540
557
|
fs.writeFileSync(CURSOR_HOOKS_PATH, JSON.stringify(hooksFile, null, 2), "utf8");
|
|
541
558
|
}
|
|
542
559
|
function parseClaudeCodeStats(content) {
|