codiedev 0.9.63 → 0.9.64

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.
@@ -64,10 +64,10 @@ exports.sweepCodexLimits = sweepCodexLimits;
64
64
  // after the block: in one real 44 MB rollout the marker sat 1.13 MB from the
65
65
  // end, outside the window, and the parse returned null.
66
66
  const fs = __importStar(require("fs"));
67
- const os = __importStar(require("os"));
68
67
  const path = __importStar(require("path"));
69
68
  const limitEvent_1 = require("./limitEvent");
70
69
  const configDir_1 = require("./configDir");
70
+ const harnessDirs_1 = require("./harnessDirs");
71
71
  const MARKER = Buffer.from("rate_limit_reached_type");
72
72
  const SPEND_MARKER = Buffer.from("spend_control_reached");
73
73
  const NEWLINE = 0x0a;
@@ -269,7 +269,7 @@ function sessionIdFromRolloutPath(filePath) {
269
269
  }
270
270
  /** Where Codex writes its rollout JSONL files. */
271
271
  function codexSessionsDir() {
272
- return path.join(os.homedir(), ".codex", "sessions");
272
+ return path.join((0, harnessDirs_1.codexHome)(), "sessions");
273
273
  }
274
274
  exports.CODEX_LIMIT_STATE_PATH = path.join((0, configDir_1.codiedevStateDir)(), "codex-limit-state.json");
275
275
  // Bounds the state file on a machine with a long Codex history.
@@ -57,6 +57,7 @@ exports.parseCodieArgs = parseCodieArgs;
57
57
  exports.validateCodieArgs = validateCodieArgs;
58
58
  const path = __importStar(require("path"));
59
59
  const url_1 = require("url");
60
+ const harnessDirs_1 = require("./harnessDirs");
60
61
  const DEFAULT_NAMES = {
61
62
  "openai/gpt-5.3-codex": "GPT-5.3 Codex",
62
63
  "openai/gpt-5.2-codex": "GPT-5.2 Codex",
@@ -342,7 +343,7 @@ function patchBrandWordmark(binary) {
342
343
  return { changed: true, offset: matches[0], stock, replacement: Buffer.from(exports.HIDDEN_WORDMARK) };
343
344
  }
344
345
  function resolveCapturePlugin({ homeDir, existsSync, }) {
345
- const capturePath = path.join(homeDir, ".config", "opencode", "plugins", "codiedev.js");
346
+ const capturePath = path.join((0, harnessDirs_1.openCodeConfigDir)(process.env, homeDir), "plugins", "codiedev.js");
346
347
  if (!existsSync(capturePath)) {
347
348
  throw new Error("Codiedev session capture is not installed. Run `codiedev connect` first");
348
349
  }
@@ -1 +1,9 @@
1
+ type CheckStatus = "pass" | "fail" | "warn";
2
+ interface CheckResult {
3
+ name: string;
4
+ status: CheckStatus;
5
+ detail?: string;
6
+ }
7
+ export declare function configDirInUseCheck(agent: string, dir: string, inUse: boolean, envVar: string): CheckResult;
1
8
  export declare function runDoctor(_args: string[]): Promise<void>;
9
+ export {};
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.configDirInUseCheck = configDirInUseCheck;
36
37
  exports.runDoctor = runDoctor;
37
38
  const fs = __importStar(require("fs"));
38
39
  const path = __importStar(require("path"));
@@ -46,12 +47,26 @@ const upgradeNudge_1 = require("../upgradeNudge");
46
47
  const captureReadiness_1 = require("../captureReadiness");
47
48
  const captureLog_1 = require("../captureLog");
48
49
  const copilotInstallation_1 = require("../copilotInstallation");
49
- const CLAUDE_SETTINGS_PATH = path.join(os.homedir(), ".claude", "settings.json");
50
- const CLAUDE_INSTRUCTIONS_PATH = path.join(os.homedir(), ".claude", "CLAUDE.md");
51
- const CODEX_HOOKS_PATH = path.join(os.homedir(), ".codex", "hooks.json");
52
- const CODEX_INSTRUCTIONS_PATH = path.join(os.homedir(), ".codex", "AGENTS.md");
50
+ const harnessDirs_1 = require("../harnessDirs");
51
+ const CLAUDE_DIR = (0, harnessDirs_1.claudeConfigDir)();
52
+ const CLAUDE_SETTINGS_PATH = path.join(CLAUDE_DIR, "settings.json");
53
+ const CLAUDE_INSTRUCTIONS_PATH = path.join(CLAUDE_DIR, "CLAUDE.md");
54
+ const CODEX_DIR = (0, harnessDirs_1.codexHome)();
55
+ const CODEX_HOOKS_PATH = path.join(CODEX_DIR, "hooks.json");
56
+ const CODEX_INSTRUCTIONS_PATH = path.join(CODEX_DIR, "AGENTS.md");
53
57
  const CURSOR_HOOKS_PATH = path.join(os.homedir(), ".cursor", "hooks.json");
54
58
  const CURSOR_INSTRUCTIONS_PATH = path.join(os.homedir(), ".cursor", "rules", "codiedev.mdc");
59
+ function configDirInUseCheck(agent, dir, inUse, envVar) {
60
+ return {
61
+ name: `${agent} reads this config dir`,
62
+ status: inUse ? "pass" : "warn",
63
+ detail: inUse
64
+ ? (0, harnessDirs_1.displayPath)(dir)
65
+ : `no ${agent} activity in ${(0, harnessDirs_1.displayPath)(dir)} — if you've run ${agent} here, it reads its config from ` +
66
+ `somewhere else, so the hooks below never fire. Set ${envVar} to that dir (or run as the user that runs ` +
67
+ `${agent}) and re-run \`codiedev connect\``,
68
+ };
69
+ }
55
70
  function symbol(status) {
56
71
  if (status === "pass")
57
72
  return "✓";
@@ -60,7 +75,7 @@ function symbol(status) {
60
75
  return "✗";
61
76
  }
62
77
  function codexInstalled() {
63
- return fs.existsSync(path.join(os.homedir(), ".codex"));
78
+ return fs.existsSync(CODEX_DIR);
64
79
  }
65
80
  function cursorInstalled() {
66
81
  return fs.existsSync(path.join(os.homedir(), ".cursor"));
@@ -401,20 +416,25 @@ async function runDoctor(_args) {
401
416
  checks.push({
402
417
  name: "Claude Code detected",
403
418
  status: "pass",
404
- detail: "~/.claude",
419
+ detail: (0, harnessDirs_1.displayPath)(CLAUDE_DIR),
405
420
  });
421
+ // A hook in settings.json only fires if Claude Code actually reads this
422
+ // dir. If it holds nothing Claude Code writes on use, it's running from
423
+ // somewhere else (CLAUDE_CONFIG_DIR unset in this shell, another user,
424
+ // the host vs. a container) and the ✓s below are hollow.
425
+ checks.push(configDirInUseCheck("Claude Code", CLAUDE_DIR, (0, harnessDirs_1.claudeConfigDirInUse)(CLAUDE_DIR), "CLAUDE_CONFIG_DIR"));
406
426
  checks.push({
407
427
  name: "Claude Code SessionEnd hook",
408
428
  status: hasCodiedevHook(CLAUDE_SETTINGS_PATH, "SessionEnd") ? "pass" : "fail",
409
429
  detail: hasCodiedevHook(CLAUDE_SETTINGS_PATH, "SessionEnd")
410
- ? "~/.claude/settings.json"
430
+ ? (0, harnessDirs_1.displayPath)(CLAUDE_SETTINGS_PATH)
411
431
  : "missing — re-run `codiedev connect`",
412
432
  });
413
433
  checks.push({
414
434
  name: "Claude Code agent instructions",
415
435
  status: hasCodiedevInstructions(CLAUDE_INSTRUCTIONS_PATH) ? "pass" : "fail",
416
436
  detail: hasCodiedevInstructions(CLAUDE_INSTRUCTIONS_PATH)
417
- ? "~/.claude/CLAUDE.md"
437
+ ? (0, harnessDirs_1.displayPath)(CLAUDE_INSTRUCTIONS_PATH)
418
438
  : "missing — re-run `codiedev connect`",
419
439
  });
420
440
  }
@@ -430,20 +450,21 @@ async function runDoctor(_args) {
430
450
  checks.push({
431
451
  name: "Codex detected",
432
452
  status: "pass",
433
- detail: "~/.codex",
453
+ detail: (0, harnessDirs_1.displayPath)(CODEX_DIR),
434
454
  });
455
+ checks.push(configDirInUseCheck("Codex", CODEX_DIR, (0, harnessDirs_1.codexHomeInUse)(CODEX_DIR), "CODEX_HOME"));
435
456
  checks.push({
436
457
  name: "Codex Stop hook",
437
458
  status: hasCodiedevHook(CODEX_HOOKS_PATH, "Stop") ? "pass" : "fail",
438
459
  detail: hasCodiedevHook(CODEX_HOOKS_PATH, "Stop")
439
- ? "~/.codex/hooks.json"
460
+ ? (0, harnessDirs_1.displayPath)(CODEX_HOOKS_PATH)
440
461
  : "missing — re-run `codiedev connect`",
441
462
  });
442
463
  checks.push({
443
464
  name: "Codex agent instructions",
444
465
  status: hasCodiedevInstructions(CODEX_INSTRUCTIONS_PATH) ? "pass" : "fail",
445
466
  detail: hasCodiedevInstructions(CODEX_INSTRUCTIONS_PATH)
446
- ? "~/.codex/AGENTS.md"
467
+ ? (0, harnessDirs_1.displayPath)(CODEX_INSTRUCTIONS_PATH)
447
468
  : "missing — re-run `codiedev connect`",
448
469
  });
449
470
  }
package/dist/connect.js CHANGED
@@ -39,11 +39,13 @@ const https = __importStar(require("https"));
39
39
  const http = __importStar(require("http"));
40
40
  const crypto = __importStar(require("crypto"));
41
41
  const os = __importStar(require("os"));
42
+ const path = __importStar(require("path"));
42
43
  const utils_1 = require("./utils");
43
44
  const connectFlow_1 = require("./connectFlow");
44
45
  const version_1 = require("./version");
45
46
  const upgradeNudge_1 = require("./upgradeNudge");
46
47
  const shared_1 = require("./commands/shared");
48
+ const harnessDirs_1 = require("./harnessDirs");
47
49
  // cli.codiedev.com is a Convex custom domain on the prod deployment; the
48
50
  // underlying judicious-falcon-861.convex.site URL keeps serving, so configs
49
51
  // written by older CLI versions stay valid without a re-connect.
@@ -304,12 +306,12 @@ async function runConnect(args = []) {
304
306
  }
305
307
  };
306
308
  if (hasClaude) {
307
- runInstall("claude-code-hook", utils_1.installHook, "Claude Code SessionEnd (capture) + UserPromptSubmit (skill discovery) + Stop (auto-backup) hooks (~/.claude/settings.json)", "claudeCode-hook");
308
- runInstall("claude-code-instructions", utils_1.installClaudeCodeInstructions, "Claude Code agent instructions (~/.claude/CLAUDE.md)", "claudeCode-instructions");
309
+ runInstall("claude-code-hook", utils_1.installHook, `Claude Code SessionEnd (capture) + UserPromptSubmit (skill discovery) + Stop (auto-backup) hooks (${(0, harnessDirs_1.displayPath)(path.join((0, harnessDirs_1.claudeConfigDir)(), "settings.json"))})`, "claudeCode-hook");
310
+ runInstall("claude-code-instructions", utils_1.installClaudeCodeInstructions, `Claude Code agent instructions (${(0, harnessDirs_1.displayPath)(path.join((0, harnessDirs_1.claudeConfigDir)(), "CLAUDE.md"))})`, "claudeCode-instructions");
309
311
  }
310
312
  if (hasCodex) {
311
- runInstall("codex-hook", utils_1.installCodexHook, "Codex Stop (capture + auto-backup) hooks (~/.codex/hooks.json)", "codex-hook");
312
- runInstall("codex-instructions", utils_1.installCodexInstructions, "Codex agent instructions (~/.codex/AGENTS.md)", "codex-instructions");
313
+ runInstall("codex-hook", utils_1.installCodexHook, `Codex Stop (capture + auto-backup) hooks (${(0, harnessDirs_1.displayPath)(path.join((0, harnessDirs_1.codexHome)(), "hooks.json"))})`, "codex-hook");
314
+ runInstall("codex-instructions", utils_1.installCodexInstructions, `Codex agent instructions (${(0, harnessDirs_1.displayPath)(path.join((0, harnessDirs_1.codexHome)(), "AGENTS.md"))})`, "codex-instructions");
313
315
  }
314
316
  if (hasCursor) {
315
317
  runInstall("cursor-hook", utils_1.installCursorHook, "Cursor sessionStart + stop backup + sessionEnd capture hooks (~/.cursor/hooks.json)", "cursor-hook");
@@ -324,7 +326,7 @@ async function runConnect(args = []) {
324
326
  // Always stage the adapter. It is dormant until OpenCode starts, which lets
325
327
  // a user connect Claude Code today and install the Codie harness tomorrow
326
328
  // without needing a second setup ritual.
327
- runInstall("opencode-capture-adapter", utils_1.installOpenCodeCapturePlugin, "OpenCode session capture adapter (~/.config/opencode/plugins/codiedev.js)", "opencode-capture");
329
+ runInstall("opencode-capture-adapter", utils_1.installOpenCodeCapturePlugin, `OpenCode session capture adapter (${(0, harnessDirs_1.displayPath)(path.join((0, harnessDirs_1.openCodeConfigDir)(), "plugins", "codiedev.js"))})`, "opencode-capture");
328
330
  // Tell the backend which targets we wired up so the portal's onboarding
329
331
  // card flips to "Connected" only when something actually installed —
330
332
  // not on bare token validation. Best-effort: a network failure here
@@ -0,0 +1,12 @@
1
+ /** Claude Code: `$CLAUDE_CONFIG_DIR` or ~/.claude. */
2
+ export declare function claudeConfigDir(env?: NodeJS.ProcessEnv, home?: string): string;
3
+ /** Claude Code's user state file. Lives inside `$CLAUDE_CONFIG_DIR` when set, else ~/.claude.json. */
4
+ export declare function claudeUserConfigPath(env?: NodeJS.ProcessEnv, home?: string): string;
5
+ /** Codex: `$CODEX_HOME` or ~/.codex. */
6
+ export declare function codexHome(env?: NodeJS.ProcessEnv, home?: string): string;
7
+ /** OpenCode: `$XDG_CONFIG_HOME/opencode` or ~/.config/opencode. */
8
+ export declare function openCodeConfigDir(env?: NodeJS.ProcessEnv, home?: string): string;
9
+ /** `~`-abbreviated path for user-facing output. */
10
+ export declare function displayPath(p: string, home?: string): string;
11
+ export declare function claudeConfigDirInUse(dir?: string, exists?: (p: string) => boolean): boolean;
12
+ export declare function codexHomeInUse(dir?: string, exists?: (p: string) => boolean): boolean;
@@ -0,0 +1,90 @@
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.claudeConfigDir = claudeConfigDir;
37
+ exports.claudeUserConfigPath = claudeUserConfigPath;
38
+ exports.codexHome = codexHome;
39
+ exports.openCodeConfigDir = openCodeConfigDir;
40
+ exports.displayPath = displayPath;
41
+ exports.claudeConfigDirInUse = claudeConfigDirInUse;
42
+ exports.codexHomeInUse = codexHomeInUse;
43
+ // Where each coding agent reads its user config from. Every harness lets the
44
+ // user relocate it with an env var; installing into the default dir when the
45
+ // var is set writes hooks the agent never loads (a container with
46
+ // CLAUDE_CONFIG_DIR=/home/node/.claude while HOME=/root captured nothing for
47
+ // two weeks while doctor reported ✓). Same shape as copilotHome().
48
+ //
49
+ // Imports only node built-ins so utils.ts, doctor.ts and the hook path
50
+ // can all import it without a cycle.
51
+ const fs = __importStar(require("fs"));
52
+ const os = __importStar(require("os"));
53
+ const path = __importStar(require("path"));
54
+ function override(value) {
55
+ const trimmed = value?.trim();
56
+ return trimmed ? path.resolve(trimmed) : undefined;
57
+ }
58
+ /** Claude Code: `$CLAUDE_CONFIG_DIR` or ~/.claude. */
59
+ function claudeConfigDir(env = process.env, home = os.homedir()) {
60
+ return override(env.CLAUDE_CONFIG_DIR) ?? path.join(home, ".claude");
61
+ }
62
+ /** Claude Code's user state file. Lives inside `$CLAUDE_CONFIG_DIR` when set, else ~/.claude.json. */
63
+ function claudeUserConfigPath(env = process.env, home = os.homedir()) {
64
+ const dir = override(env.CLAUDE_CONFIG_DIR);
65
+ return dir ? path.join(dir, ".claude.json") : path.join(home, ".claude.json");
66
+ }
67
+ /** Codex: `$CODEX_HOME` or ~/.codex. */
68
+ function codexHome(env = process.env, home = os.homedir()) {
69
+ return override(env.CODEX_HOME) ?? path.join(home, ".codex");
70
+ }
71
+ /** OpenCode: `$XDG_CONFIG_HOME/opencode` or ~/.config/opencode. */
72
+ function openCodeConfigDir(env = process.env, home = os.homedir()) {
73
+ return path.join(override(env.XDG_CONFIG_HOME) ?? path.join(home, ".config"), "opencode");
74
+ }
75
+ /** `~`-abbreviated path for user-facing output. */
76
+ function displayPath(p, home = os.homedir()) {
77
+ return p === home || p.startsWith(home + path.sep) ? "~" + p.slice(home.length) : p;
78
+ }
79
+ // Files/dirs Claude Code writes on first real use. Our installer only writes
80
+ // settings.json + CLAUDE.md, so a dir holding nothing but those is one Claude
81
+ // Code has never run against — the hooks in it will never fire.
82
+ const CLAUDE_USAGE_MARKERS = ["projects", "history.jsonl", "sessions", "statsig", "todos", "shell-snapshots"];
83
+ function claudeConfigDirInUse(dir = claudeConfigDir(), exists = fs.existsSync) {
84
+ return CLAUDE_USAGE_MARKERS.some((m) => exists(path.join(dir, m)));
85
+ }
86
+ // Codex writes rollouts under sessions/ and keeps history.jsonl alongside.
87
+ const CODEX_USAGE_MARKERS = ["sessions", "history.jsonl", "auth.json"];
88
+ function codexHomeInUse(dir = codexHome(), exists = fs.existsSync) {
89
+ return CODEX_USAGE_MARKERS.some((m) => exists(path.join(dir, m)));
90
+ }
package/dist/utils.js CHANGED
@@ -133,6 +133,7 @@ const codexHookTrust_1 = require("./codexHookTrust");
133
133
  const teamSkillContext_1 = require("./teamSkillContext");
134
134
  const nativeSteering_1 = require("./nativeSteering");
135
135
  const copilotHooks_1 = require("./copilotHooks");
136
+ const harnessDirs_1 = require("./harnessDirs");
136
137
  const CONFIG_DIR = (0, configDir_1.codiedevStateDir)();
137
138
  exports.CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
138
139
  function readConfig() {
@@ -886,12 +887,12 @@ function hashToken(token) {
886
887
  }
887
888
  return hash.toString(36);
888
889
  }
889
- const CLAUDE_SETTINGS_PATH = path.join(os.homedir(), ".claude", "settings.json");
890
- const CLAUDE_DIR = path.join(os.homedir(), ".claude");
891
- const CODEX_HOOKS_PATH = path.join(os.homedir(), ".codex", "hooks.json");
892
- const CODEX_DIR = path.join(os.homedir(), ".codex");
890
+ const CLAUDE_SETTINGS_PATH = path.join((0, harnessDirs_1.claudeConfigDir)(), "settings.json");
891
+ const CLAUDE_DIR = (0, harnessDirs_1.claudeConfigDir)();
892
+ const CODEX_HOOKS_PATH = path.join((0, harnessDirs_1.codexHome)(), "hooks.json");
893
+ const CODEX_DIR = (0, harnessDirs_1.codexHome)();
893
894
  const CURSOR_DIR = path.join(os.homedir(), ".cursor");
894
- const OPENCODE_DIR = path.join(os.homedir(), ".config", "opencode");
895
+ const OPENCODE_DIR = (0, harnessDirs_1.openCodeConfigDir)();
895
896
  const OPENCODE_PLUGIN_DIR = path.join(OPENCODE_DIR, "plugins");
896
897
  const OPENCODE_PLUGIN_PATH = path.join(OPENCODE_PLUGIN_DIR, "codiedev.js");
897
898
  const CURSOR_HOOKS_PATH = path.join(CURSOR_DIR, "hooks.json");
@@ -1433,10 +1434,10 @@ function ensureSessionStartHookInstalled() {
1433
1434
  // MCP server installation — writes the codiedev MCP server config into each
1434
1435
  // agent CLI's expected location so "npx codiedev connect" wires it up once.
1435
1436
  // ─────────────────────────────────────────────────────────────────────────────
1436
- const CLAUDE_USER_CONFIG_PATH = path.join(os.homedir(), ".claude.json");
1437
- const CLAUDE_USER_INSTRUCTIONS_PATH = path.join(os.homedir(), ".claude", "CLAUDE.md");
1438
- const CODEX_USER_INSTRUCTIONS_PATH = path.join(os.homedir(), ".codex", "AGENTS.md");
1439
- const CODEX_CONFIG_PATH = path.join(os.homedir(), ".codex", "config.toml");
1437
+ const CLAUDE_USER_CONFIG_PATH = (0, harnessDirs_1.claudeUserConfigPath)();
1438
+ const CLAUDE_USER_INSTRUCTIONS_PATH = path.join((0, harnessDirs_1.claudeConfigDir)(), "CLAUDE.md");
1439
+ const CODEX_USER_INSTRUCTIONS_PATH = path.join((0, harnessDirs_1.codexHome)(), "AGENTS.md");
1440
+ const CODEX_CONFIG_PATH = path.join((0, harnessDirs_1.codexHome)(), "config.toml");
1440
1441
  const CODIEDEV_INSTRUCTIONS_BEGIN = "<!-- codiedev-cli:begin -->";
1441
1442
  const CODIEDEV_INSTRUCTIONS_END = "<!-- codiedev-cli:end -->";
1442
1443
  const CODIEDEV_INSTRUCTIONS_BODY = `## Codiedev — team artifact layer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codiedev",
3
- "version": "0.9.63",
3
+ "version": "0.9.64",
4
4
  "description": "Connect Claude Code, Codex, Cursor, OpenCode, or VS Code Copilot to Codiedev for team session capture and artifact collaboration — and run the governed Codie harness",
5
5
  "bin": {
6
6
  "codiedev": "dist/cli.js",