codiedev 0.7.10 → 0.7.11

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/detection.js CHANGED
@@ -4,6 +4,7 @@
4
4
  // mocking fs or process.
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.detectClaudeCode = detectClaudeCode;
7
+ exports.isCodiedevHookCommand = isCodiedevHookCommand;
7
8
  /**
8
9
  * Claude Code is "installed" if either ~/.claude exists (the user has
9
10
  * launched the app at least once) OR the `claude` binary is on PATH (the
@@ -14,3 +15,30 @@ exports.detectClaudeCode = detectClaudeCode;
14
15
  function detectClaudeCode(probe) {
15
16
  return probe.dirExists || probe.binOnPath;
16
17
  }
18
+ /**
19
+ * True iff `cmd` looks like a hook command codiedev itself wrote. Used
20
+ * both by the install filter (so `connect` replaces the existing entry
21
+ * instead of stacking another one) and by `codiedev doctor` (so it can
22
+ * grade whether the hook is wired up).
23
+ *
24
+ * Must match every form codiedev can write:
25
+ * - Legacy `npx codiedev-hook <subcommand>`
26
+ * - Absolute path from npm-registry install:
27
+ * `<node> /.../node_modules/codiedev/dist/hook.js <subcommand>`
28
+ * - Absolute path from `npm link` dev install (the monorepo folder
29
+ * is named `codiedev-cli`, not `codiedev`):
30
+ * `<node> /.../codiedev-cli/dist/hook.js <subcommand>`
31
+ *
32
+ * The `codiedev[^/\\]*` allows the trailing `-cli` (or any future suffix)
33
+ * without matching unrelated paths like `notcodiedev/dist/hook.js`.
34
+ */
35
+ function isCodiedevHookCommand(cmd) {
36
+ if (!cmd)
37
+ return false;
38
+ if (cmd.includes("codiedev-hook"))
39
+ return true;
40
+ // Anchor at a path separator (or string start) so we don't match
41
+ // unrelated paths like `notcodiedev/dist/hook.js` that happen to contain
42
+ // the substring `codiedev`.
43
+ return /(?:^|[\\/])codiedev[^/\\]*[\\/]dist[\\/]hook/.test(cmd);
44
+ }
package/dist/hook.js CHANGED
File without changes
package/dist/mcp.js CHANGED
@@ -173,8 +173,8 @@ const TOOLS = [
173
173
  name: "codiedev_ping",
174
174
  description: "Send a message to a teammate on CodieDev, optionally attached to a " +
175
175
  "specific artifact. Use when the user asks to ping, ask, share with, " +
176
- "or get feedback from a teammate by name (e.g. 'ping Maya about this " +
177
- "spec'). Recipients are resolved by first name, full name, or email " +
176
+ "or get feedback from a teammate by name (e.g. 'ping a teammate about " +
177
+ "this spec'). Recipients are resolved by first name, full name, or email " +
178
178
  "within the current org. They're notified by email and can reply " +
179
179
  "from their own agent.",
180
180
  inputSchema: {
@@ -325,8 +325,8 @@ const TOOLS = [
325
325
  name: "codiedev_share_with",
326
326
  description: "Grant a teammate persistent read (or edit) access to an artifact " +
327
327
  "without sending a notification. Use when the user says 'share this " +
328
- "with Greg' or 'give Jason access', and doesn't want to surface it " +
329
- "as a message. If they want the teammate actively notified, use " +
328
+ "with a teammate' or 'give someone access', and doesn't want to surface " +
329
+ "it as a message. If they want the teammate actively notified, use " +
330
330
  "codiedev_send_to instead.",
331
331
  inputSchema: {
332
332
  type: "object",
@@ -349,8 +349,8 @@ const TOOLS = [
349
349
  {
350
350
  name: "codiedev_send_to",
351
351
  description: "Grant access to an artifact AND send a short message to a " +
352
- "teammate. Use when the user asks to 'send this to Greg', 'ask " +
353
- "Greg to look at this', or 'share this with Jason and tell him X'. " +
352
+ "teammate. Use when the user asks to 'send this to a teammate', 'ask " +
353
+ "someone to look at this', or 'share this with a teammate and tell them X'. " +
354
354
  "This is the active handoff version of codiedev_share_with — the " +
355
355
  "recipient gets a ping in their inbox.",
356
356
  inputSchema: {
@@ -439,7 +439,7 @@ const TOOLS = [
439
439
  "files surfaced as slash commands). Each row reports its `kind` " +
440
440
  "(doc | skill) and `tags`. Use when the user asks 'show me my " +
441
441
  "artifacts', 'what skills do we have?', 'what did I push?', 'what " +
442
- "has Greg shared with me?', or 'browse the library'. Filter by " +
442
+ "has a teammate shared with me?', or 'browse the library'. Filter by " +
443
443
  "`kind` to narrow to docs-only or skills-only.",
444
444
  inputSchema: {
445
445
  type: "object",
package/dist/utils.d.ts CHANGED
@@ -61,6 +61,28 @@ export declare function installCursorMcp(): void;
61
61
  * 100% diff-driven (no transcript dependency).
62
62
  */
63
63
  export declare function installVSCodeMcp(): void;
64
+ /**
65
+ * Removes `mcpServers.codiedev` from `~/.claude.json` if present. Leaves
66
+ * other MCP servers and unrelated top-level settings untouched.
67
+ */
68
+ export declare function cleanupClaudeCodeMcp(): void;
69
+ /**
70
+ * Removes `mcpServers.codiedev` from `~/.cursor/mcp.json` if present.
71
+ */
72
+ export declare function cleanupCursorMcp(): void;
73
+ /**
74
+ * Removes `servers.codiedev` from VS Code's user-scope mcp.json. VS Code
75
+ * uses a different schema (`servers` not `mcpServers`), so this is a
76
+ * separate helper.
77
+ */
78
+ export declare function cleanupVSCodeMcp(): void;
79
+ /**
80
+ * Removes the `# codiedev-mcp` block from `~/.codex/config.toml`. The
81
+ * install side appends a well-marked block; we strip it the same way —
82
+ * the marker line through the end of its TOML section. Whitespace-only
83
+ * gaps between sections are preserved.
84
+ */
85
+ export declare function cleanupCodexMcp(): void;
64
86
  /**
65
87
  * Best-effort append of the CodieDev MCP server block to ~/.codex/config.toml.
66
88
  *
package/dist/utils.js CHANGED
@@ -50,6 +50,10 @@ exports.installCursorInstructions = installCursorInstructions;
50
50
  exports.installClaudeCodeMcp = installClaudeCodeMcp;
51
51
  exports.installCursorMcp = installCursorMcp;
52
52
  exports.installVSCodeMcp = installVSCodeMcp;
53
+ exports.cleanupClaudeCodeMcp = cleanupClaudeCodeMcp;
54
+ exports.cleanupCursorMcp = cleanupCursorMcp;
55
+ exports.cleanupVSCodeMcp = cleanupVSCodeMcp;
56
+ exports.cleanupCodexMcp = cleanupCodexMcp;
53
57
  exports.installCodexMcp = installCodexMcp;
54
58
  exports.installCodexHook = installCodexHook;
55
59
  exports.installCursorHook = installCursorHook;
@@ -186,11 +190,8 @@ function resolveHookCommand(subcommand) {
186
190
  }
187
191
  return `npx codiedev-hook ${subcommand}`;
188
192
  }
189
- function isCodiedevHookCommand(cmd) {
190
- if (!cmd)
191
- return false;
192
- return cmd.includes("codiedev-hook") || /codiedev[\\/]dist[\\/]hook/.test(cmd);
193
- }
193
+ // `isCodiedevHookCommand` is defined in `./detection` so it's testable
194
+ // without mocking fs/path. Re-imported below; do not re-define here.
194
195
  function claudeBinOnPath() {
195
196
  try {
196
197
  (0, child_process_1.execSync)("command -v claude", { stdio: ["pipe", "pipe", "pipe"] });
@@ -254,9 +255,9 @@ function installHook() {
254
255
  const filtered = existing.filter((hook) => {
255
256
  const inner = hook.hooks;
256
257
  if (Array.isArray(inner)) {
257
- return !inner.some((h) => isCodiedevHookCommand(h.command));
258
+ return !inner.some((h) => (0, detection_1.isCodiedevHookCommand)(h.command));
258
259
  }
259
- return !isCodiedevHookCommand(hook.matcher);
260
+ return !(0, detection_1.isCodiedevHookCommand)(hook.matcher);
260
261
  });
261
262
  filtered.push({
262
263
  matcher: ".*",
@@ -294,20 +295,20 @@ thought, use the \`codiedev\` CLI via Bash:**
294
295
  | Intent | Command |
295
296
  |---|---|
296
297
  | "push this spec" / "save this as a skill" | \`codiedev push <file.md>\` |
297
- | "pull X" / "grab the latest spec-X" / "what did Maya push?" | \`codiedev pull <key>\` |
298
+ | "pull X" / "grab the latest spec-X" / "what did a teammate push?" | \`codiedev pull <key>\` |
298
299
  | "delete X" / "remove that test push" / "rm spec-old" | \`codiedev delete <key>\` (always confirm with the user first) |
299
- | "ping Nic about this" / "ask Maya for her take" | \`codiedev ping <name> "<msg>" [--with <key>]\` |
300
- | "any messages?" / "check my inbox" / "what did Nic say?" | \`codiedev inbox\` |
301
- | "read Nic's reply" / "mark that ping read" | \`codiedev read <ping-id>\` |
300
+ | "ping a teammate about this" / "ask someone for their take" | \`codiedev ping <name> "<msg>" [--with <key>]\` |
301
+ | "any messages?" / "check my inbox" / "what did a teammate say?" | \`codiedev inbox\` |
302
+ | "read that reply" / "mark that ping read" | \`codiedev read <ping-id>\` |
302
303
  | "note that X is a follow-up" / "remember X" | \`codiedev note "<text>"\` |
303
304
  | "promote the extracted spec" | \`codiedev promote <artifact-id>\` |
304
- | "post this to the team" / "publish to the feed" / "share with the team" | MCP tool \`codiedev_post_to_feed\` |
305
- | "share with Greg" / "give Jason access" (no notification) | MCP tool \`codiedev_share_with\` |
306
- | "send this to Greg" / "ask Greg to look at this" | MCP tool \`codiedev_send_to\` |
307
- | "find something about X" / "has anyone solved Y?" | MCP tool \`codiedev_search\` |
308
- | "why did we…?" / "what does the team know about X?" | MCP tool \`codiedev_ask\` (synthesized answer + citations) |
309
- | "show my library" / "what artifacts exist?" | MCP tool \`codiedev_get_library\` |
310
- | "react 🛠 to that post" / "mark as used" | MCP tool \`codiedev_react\` |
305
+ | "post this to the team" / "publish to the feed" / "share with the team" | \`codiedev post --title "<t>" --body "<b>" [--intent <intent>] [--filename <key>] [--mention <name>]\` |
306
+ | "share with a teammate" / "give someone access" (no notification) | \`codiedev share <key> <name> [--role read\\|edit]\` |
307
+ | "send this to a teammate" / "ask someone to look at this" | \`codiedev send <key> <name> ["<msg>"]\` |
308
+ | "find something about X" / "has anyone solved Y?" | \`codiedev search "<query>" [--limit N]\` |
309
+ | "why did we…?" / "what does the team know about X?" | \`codiedev ask "<question>"\` (synthesized answer + citations) |
310
+ | "show my library" / "what artifacts exist?" | \`codiedev library [--scope mine\\|shared\\|all] [--kind doc\\|skill]\` |
311
+ | "react 🛠 to that post" / "mark as used" | \`codiedev react <postId> <emoji>\` |
311
312
 
312
313
  **Just push the file — we'll figure out where it goes.** Every artifact
313
314
  is classified into one of two kinds at upload time:
@@ -332,16 +333,17 @@ read it back to the user so they can confirm.
332
333
  - If content was drafted inline in the conversation, write it to a file
333
334
  first (e.g., \`/tmp/spec-xxx.md\`) then push.
334
335
 
335
- **Teammate names:** first name usually works (\`codiedev ping nic ...\`).
336
+ **Teammate names:** first name usually works (\`codiedev ping <name> ...\`).
336
337
  If ambiguous, the CLI returns candidates — retry with the full email.
337
338
 
338
- **Feed posts (broad team reach):** use \`codiedev_post_to_feed\` when the
339
- user wants visibility beyond one teammate — e.g., announcing a new skill,
340
- asking the team who knows about X, proposing a change. Always pass an
341
- \`intent\` that matches the request: \`share\` (here's a skill),
339
+ **Feed posts (broad team reach):** use \`codiedev post\` when the user
340
+ wants visibility beyond one teammate — e.g., announcing a new skill,
341
+ asking the team who knows about X, proposing a change. Always pass
342
+ \`--intent\` to match the request: \`share\` (here's a skill),
342
343
  \`request_review\`, \`request_expertise\` (stuck, who knows this),
343
- \`link_share\` (fyi), or \`rfc\` (proposing a change). Attach a \`filename\`
344
- to link a specific artifact and \`mentions\` to tag teammates.
344
+ \`link_share\` (fyi), or \`rfc\` (proposing a change). Pass \`--filename\`
345
+ to link a specific artifact and \`--mention <name>\` (repeatable) to
346
+ tag teammates.
345
347
 
346
348
  **Default feed-post shape.** When the user explicitly says "push/share/post
347
349
  to the feed", default to this shape unless they ask for something else:
@@ -359,12 +361,12 @@ to the feed", default to this shape unless they ask for something else:
359
361
  This is the default. If the user wants a one-liner or a different
360
362
  structure, follow their lead.
361
363
 
362
- **Search before pushing.** For any "save this as …" request, call
363
- \`codiedev_search\` first with a relevant query. If prior art exists, pull
364
- it and iterate rather than duplicating.
364
+ **Search before pushing.** For any "save this as …" request, run
365
+ \`codiedev search "<query>"\` first. If prior art exists, pull it and
366
+ iterate rather than duplicating.
365
367
 
366
- **Sharing vs sending:** \`codiedev_share_with\` is silent (access only, no
367
- notification). \`codiedev_send_to\` both grants access AND pings the
368
+ **Sharing vs sending:** \`codiedev share\` is silent (access only, no
369
+ notification). \`codiedev send\` both grants access AND pings the
368
370
  recipient. Use send when the user is actively looping someone in.
369
371
 
370
372
  **Errors:**
@@ -538,6 +540,94 @@ function installVSCodeMcp() {
538
540
  config.servers = servers;
539
541
  fs.writeFileSync(VSCODE_USER_MCP_PATH, JSON.stringify(config, null, 2), "utf8");
540
542
  }
543
+ // ─────────────────────────────────────────────────────────────────────────────
544
+ // Migration cleanup — strips MCP server entries written by pre-CLI-only
545
+ // versions of `codiedev connect`. Those entries pointed at `npx codiedev-mcp`,
546
+ // a binary that was removed from package.json in 0.3.4. Without these
547
+ // cleanups, customers who upgrade to 0.7.11+ keep seeing "MCP server failed
548
+ // to start" errors in their agent UIs even though the CLI works fine.
549
+ // All cleanup helpers are idempotent and safe to run when no entry exists.
550
+ // ─────────────────────────────────────────────────────────────────────────────
551
+ function removeJsonKey(filePath, parentKey) {
552
+ if (!fs.existsSync(filePath))
553
+ return;
554
+ let parsed;
555
+ try {
556
+ parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
557
+ }
558
+ catch {
559
+ return; // Don't damage a file we can't parse.
560
+ }
561
+ const parent = parsed[parentKey];
562
+ if (!parent || typeof parent !== "object")
563
+ return;
564
+ if (!("codiedev" in parent))
565
+ return;
566
+ delete parent.codiedev;
567
+ fs.writeFileSync(filePath, JSON.stringify(parsed, null, 2), "utf8");
568
+ }
569
+ /**
570
+ * Removes `mcpServers.codiedev` from `~/.claude.json` if present. Leaves
571
+ * other MCP servers and unrelated top-level settings untouched.
572
+ */
573
+ function cleanupClaudeCodeMcp() {
574
+ removeJsonKey(CLAUDE_USER_CONFIG_PATH, "mcpServers");
575
+ }
576
+ /**
577
+ * Removes `mcpServers.codiedev` from `~/.cursor/mcp.json` if present.
578
+ */
579
+ function cleanupCursorMcp() {
580
+ removeJsonKey(CURSOR_MCP_PATH, "mcpServers");
581
+ }
582
+ /**
583
+ * Removes `servers.codiedev` from VS Code's user-scope mcp.json. VS Code
584
+ * uses a different schema (`servers` not `mcpServers`), so this is a
585
+ * separate helper.
586
+ */
587
+ function cleanupVSCodeMcp() {
588
+ removeJsonKey(VSCODE_USER_MCP_PATH, "servers");
589
+ }
590
+ /**
591
+ * Removes the `# codiedev-mcp` block from `~/.codex/config.toml`. The
592
+ * install side appends a well-marked block; we strip it the same way —
593
+ * the marker line through the end of its TOML section. Whitespace-only
594
+ * gaps between sections are preserved.
595
+ */
596
+ function cleanupCodexMcp() {
597
+ if (!fs.existsSync(CODEX_CONFIG_PATH))
598
+ return;
599
+ const existing = fs.readFileSync(CODEX_CONFIG_PATH, "utf8");
600
+ const marker = "# codiedev-mcp";
601
+ if (!existing.includes(marker))
602
+ return;
603
+ const lines = existing.split("\n");
604
+ const out = [];
605
+ let skipping = false;
606
+ for (const line of lines) {
607
+ if (line.trim() === marker) {
608
+ skipping = true;
609
+ continue;
610
+ }
611
+ if (skipping) {
612
+ // Stay in skip mode through the [mcp_servers.codiedev] block until
613
+ // we hit a blank line or a different TOML section header.
614
+ const trimmed = line.trim();
615
+ if (trimmed === "") {
616
+ skipping = false;
617
+ continue; // also drop the blank that immediately follows the block
618
+ }
619
+ if (trimmed.startsWith("[") && !trimmed.startsWith("[mcp_servers.codiedev")) {
620
+ skipping = false;
621
+ out.push(line);
622
+ continue;
623
+ }
624
+ // Skip lines belonging to the codiedev block.
625
+ continue;
626
+ }
627
+ out.push(line);
628
+ }
629
+ fs.writeFileSync(CODEX_CONFIG_PATH, out.join("\n"), "utf8");
630
+ }
541
631
  /**
542
632
  * Best-effort append of the CodieDev MCP server block to ~/.codex/config.toml.
543
633
  *
@@ -592,7 +682,7 @@ function installCodexHook() {
592
682
  const inner = hook.hooks;
593
683
  if (!Array.isArray(inner))
594
684
  return true;
595
- return !inner.some((h) => isCodiedevHookCommand(h.command));
685
+ return !inner.some((h) => (0, detection_1.isCodiedevHookCommand)(h.command));
596
686
  });
597
687
  filtered.push({
598
688
  hooks: [
@@ -638,7 +728,7 @@ function installCursorHook() {
638
728
  hooks.sessionEnd = [];
639
729
  }
640
730
  const existing = hooks.sessionEnd;
641
- const filtered = existing.filter((h) => !isCodiedevHookCommand(h.command));
731
+ const filtered = existing.filter((h) => !(0, detection_1.isCodiedevHookCommand)(h.command));
642
732
  filtered.push({
643
733
  command: resolveHookCommand("capture-cursor"),
644
734
  type: "command",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codiedev",
3
- "version": "0.7.10",
3
+ "version": "0.7.11",
4
4
  "description": "Connect Claude Code, Codex, Cursor, or VS Code Copilot to CodieDev for org-wide session capture and artifact collaboration",
5
5
  "bin": {
6
6
  "codiedev": "dist/cli.js",