codiedev 0.10.0-beta.4 → 0.10.0-beta.6

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 (157) hide show
  1. package/README.md +11 -5
  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 +68 -3
  10. package/dist/cli.js +75 -64
  11. package/dist/codexHookTrust.js +125 -6
  12. package/dist/codexLimitScan.js +2 -109
  13. package/dist/codie.js +50 -114
  14. package/dist/codieBrandInstall.js +0 -18
  15. package/dist/codieLauncher.js +20 -92
  16. package/dist/codieRuntime.js +19 -23
  17. package/dist/codieRuntimeInstall.js +108 -23
  18. package/dist/codieUsage.js +38 -41
  19. package/dist/commands/agentTemplates.generated.js +136 -0
  20. package/dist/commands/agents.js +1066 -0
  21. package/dist/commands/agentsSdk.generated.js +7 -0
  22. package/dist/commands/ask.js +0 -3
  23. package/dist/commands/capture.js +0 -2
  24. package/dist/commands/createTicket.js +0 -10
  25. package/dist/commands/doctor.js +53 -120
  26. package/dist/commands/evals.js +187 -0
  27. package/dist/commands/inbox.js +0 -2
  28. package/dist/commands/library.js +0 -3
  29. package/dist/commands/pack.js +573 -0
  30. package/dist/commands/ping.js +0 -2
  31. package/dist/commands/pull.js +6 -10
  32. package/dist/commands/push.js +2 -12
  33. package/dist/commands/search.js +0 -4
  34. package/dist/commands/send.js +0 -5
  35. package/dist/commands/share.js +0 -4
  36. package/dist/commands/shared.js +0 -35
  37. package/dist/commands/traces.js +344 -0
  38. package/dist/commands/tracesLabel.js +348 -0
  39. package/dist/configDir.js +0 -10
  40. package/dist/connect.js +19 -116
  41. package/dist/connectFlow.js +0 -9
  42. package/dist/copilotHooks.js +391 -0
  43. package/dist/copilotInstallation.js +64 -0
  44. package/dist/cursorHooks.js +38 -30
  45. package/dist/cursorLifecycle.js +109 -0
  46. package/dist/detection.js +0 -30
  47. package/dist/harnessDirs.js +77 -0
  48. package/dist/hook.js +182 -469
  49. package/dist/inboxFormat.js +0 -24
  50. package/dist/launchContext.js +150 -0
  51. package/dist/launcher.js +140 -0
  52. package/dist/limitEvent.js +41 -35
  53. package/dist/limitEventReporter.js +1 -1
  54. package/dist/managedPi.js +240 -0
  55. package/dist/mcp.js +3 -384
  56. package/dist/nativeSteering.js +24 -0
  57. package/dist/packs/codie.js +182 -0
  58. package/dist/packs/harnesses.js +411 -0
  59. package/dist/packs/hookGate.js +256 -0
  60. package/dist/packs/install.js +286 -0
  61. package/dist/packs/manifest.js +126 -0
  62. package/dist/packs/paths.js +81 -0
  63. package/dist/packs/shim.js +214 -0
  64. package/dist/packs/store.js +155 -0
  65. package/dist/packs/sync.js +170 -0
  66. package/dist/piHooks.js +216 -0
  67. package/dist/piRuntime.js +120 -0
  68. package/dist/repoResolver.js +0 -19
  69. package/dist/secret.js +0 -3
  70. package/dist/selfUpdate.js +376 -0
  71. package/dist/skillMarker.js +23 -0
  72. package/dist/subagents.js +135 -0
  73. package/dist/teamSkillContext.js +10 -0
  74. package/dist/transcriptModels.js +6 -8
  75. package/dist/upgradeNudge.js +0 -30
  76. package/dist/utils.js +494 -824
  77. package/dist/version.js +0 -10
  78. package/dist/versionCheck.js +0 -33
  79. package/package.json +8 -9
  80. package/dist/backup/cache.d.ts +0 -14
  81. package/dist/backup/match.d.ts +0 -2
  82. package/dist/backup/run.d.ts +0 -25
  83. package/dist/captureExclusions.d.ts +0 -30
  84. package/dist/captureLog.d.ts +0 -20
  85. package/dist/captureReadiness.d.ts +0 -65
  86. package/dist/captureSignals.d.ts +0 -19
  87. package/dist/cli.d.ts +0 -16
  88. package/dist/codexHookTrust.d.ts +0 -34
  89. package/dist/codexLimitScan.d.ts +0 -64
  90. package/dist/codie.d.ts +0 -2
  91. package/dist/codieBrandInstall.d.ts +0 -11
  92. package/dist/codieLauncher.d.ts +0 -86
  93. package/dist/codieRuntime.d.ts +0 -29
  94. package/dist/codieRuntimeInstall.d.ts +0 -28
  95. package/dist/codieStartup.d.ts +0 -26
  96. package/dist/codieStartup.js +0 -30
  97. package/dist/codieUsage.d.ts +0 -57
  98. package/dist/commands/ask.d.ts +0 -1
  99. package/dist/commands/capture.d.ts +0 -14
  100. package/dist/commands/createTicket.d.ts +0 -27
  101. package/dist/commands/delete.d.ts +0 -1
  102. package/dist/commands/doctor.d.ts +0 -1
  103. package/dist/commands/inbox.d.ts +0 -3
  104. package/dist/commands/library.d.ts +0 -2
  105. package/dist/commands/note.d.ts +0 -1
  106. package/dist/commands/ping.d.ts +0 -1
  107. package/dist/commands/promote.d.ts +0 -1
  108. package/dist/commands/promote.js +0 -53
  109. package/dist/commands/pull.d.ts +0 -2
  110. package/dist/commands/push.d.ts +0 -33
  111. package/dist/commands/react.d.ts +0 -2
  112. package/dist/commands/react.js +0 -40
  113. package/dist/commands/reverseTicket.d.ts +0 -2
  114. package/dist/commands/reverseTicket.js +0 -477
  115. package/dist/commands/search.d.ts +0 -2
  116. package/dist/commands/security.d.ts +0 -1
  117. package/dist/commands/security.js +0 -156
  118. package/dist/commands/send.d.ts +0 -2
  119. package/dist/commands/share.d.ts +0 -2
  120. package/dist/commands/shared.d.ts +0 -64
  121. package/dist/configDir.d.ts +0 -1
  122. package/dist/connect.d.ts +0 -1
  123. package/dist/connectFlow.d.ts +0 -13
  124. package/dist/cursorHooks.d.ts +0 -23
  125. package/dist/detection.d.ts +0 -30
  126. package/dist/hook.d.ts +0 -6
  127. package/dist/inboxFormat.d.ts +0 -38
  128. package/dist/limitEvent.d.ts +0 -16
  129. package/dist/limitEventReporter.d.ts +0 -21
  130. package/dist/mcp.d.ts +0 -12
  131. package/dist/prUrl.d.ts +0 -9
  132. package/dist/prUrl.js +0 -33
  133. package/dist/repoResolver.d.ts +0 -17
  134. package/dist/secret.d.ts +0 -1
  135. package/dist/security.d.ts +0 -102
  136. package/dist/security.js +0 -437
  137. package/dist/securityDeepScan.d.ts +0 -41
  138. package/dist/securityDeepScan.js +0 -248
  139. package/dist/securityDoctor.d.ts +0 -32
  140. package/dist/securityDoctor.js +0 -63
  141. package/dist/securityFeature.d.ts +0 -5
  142. package/dist/securityFeature.js +0 -7
  143. package/dist/securityInstall.d.ts +0 -63
  144. package/dist/securityInstall.js +0 -239
  145. package/dist/securityInventory.d.ts +0 -54
  146. package/dist/securityInventory.js +0 -556
  147. package/dist/securityPilot.d.ts +0 -19
  148. package/dist/securityPilot.js +0 -61
  149. package/dist/securityPolicy.d.ts +0 -33
  150. package/dist/securityPolicy.js +0 -188
  151. package/dist/securitySession.d.ts +0 -6
  152. package/dist/securitySession.js +0 -72
  153. package/dist/transcriptModels.d.ts +0 -18
  154. package/dist/upgradeNudge.d.ts +0 -25
  155. package/dist/utils.d.ts +0 -346
  156. package/dist/version.d.ts +0 -1
  157. package/dist/versionCheck.d.ts +0 -68
@@ -0,0 +1,348 @@
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.parseArgs = parseArgs;
37
+ exports.scoreValue = scoreValue;
38
+ exports.runScore = runScore;
39
+ exports.runScores = runScores;
40
+ exports.runQueue = runQueue;
41
+ exports.runJudge = runJudge;
42
+ exports.runImport = runImport;
43
+ exports.runAddExample = runAddExample;
44
+ exports.runVersions = runVersions;
45
+ exports.runSaveVersion = runSaveVersion;
46
+ exports.runOverview = runOverview;
47
+ exports.runRuns = runRuns;
48
+ exports.runRun = runRun;
49
+ exports.runScoreKinds = runScoreKinds;
50
+ exports.runQueueCreate = runQueueCreate;
51
+ const fs = __importStar(require("fs"));
52
+ const path = __importStar(require("path"));
53
+ const shared_1 = require("./shared");
54
+ const BOOL_FLAGS = new Set(["--failed", "--on", "--off", "--json"]);
55
+ function parseArgs(args) {
56
+ const out = { positional: [], flags: {}, bools: new Set(), runs: [] };
57
+ for (let i = 0; i < args.length; i++) {
58
+ const a = args[i];
59
+ if (BOOL_FLAGS.has(a)) {
60
+ out.bools.add(a);
61
+ continue;
62
+ }
63
+ if (a.startsWith("--")) {
64
+ const eq = a.indexOf("=");
65
+ const name = eq > 0 ? a.slice(0, eq) : a;
66
+ const value = eq > 0 ? a.slice(eq + 1) : args[++i];
67
+ if (value === undefined)
68
+ throw new Error(`${name} needs a value`);
69
+ if (name === "--run")
70
+ out.runs.push(value);
71
+ else
72
+ out.flags[name] = value;
73
+ continue;
74
+ }
75
+ out.positional.push(a);
76
+ }
77
+ return out;
78
+ }
79
+ function scoreValue(raw) {
80
+ const t = raw.trim();
81
+ if (/^(true|false)$/i.test(t))
82
+ return t.toLowerCase() === "true";
83
+ if (t !== "" && Number.isFinite(Number(t)))
84
+ return Number(t);
85
+ return t;
86
+ }
87
+ async function call(config, tool, method, route, opts) {
88
+ const start = Date.now();
89
+ try {
90
+ const res = await (0, shared_1.apiRequest)(method, `/api/cli/traces/${route}`, { config, ...opts });
91
+ (0, shared_1.recordAgentEvent)(config, { tool, ok: true, latencyMs: Date.now() - start });
92
+ return res;
93
+ }
94
+ catch (err) {
95
+ const e = err;
96
+ (0, shared_1.recordAgentEvent)(config, { tool, ok: false, latencyMs: Date.now() - start, error: e.message });
97
+ console.error(e.message);
98
+ process.exit(1);
99
+ }
100
+ }
101
+ function usage(text) {
102
+ console.error(`Usage: ${text}`);
103
+ process.exit(1);
104
+ }
105
+ async function runScore(args, config) {
106
+ const p = parseArgs(args);
107
+ const [run, name, value] = p.positional;
108
+ if (!run || !name || value === undefined)
109
+ usage("codiedev traces score <run> <score> <value> [--agent name] [--comment text] [--step n]");
110
+ const res = await call(config, "codiedev_traces_score", "POST", "score", {
111
+ body: { run, name, value: scoreValue(value), agent: p.flags["--agent"], comment: p.flags["--comment"], ...(p.flags["--step"] ? { step: Number(p.flags["--step"]) } : {}) },
112
+ });
113
+ console.log(`✓ Scored ${res.runId}: ${name} = ${value}`);
114
+ }
115
+ async function runScores(args, config) {
116
+ const p = parseArgs(args);
117
+ const agent = p.positional[0];
118
+ if (!agent)
119
+ usage("codiedev traces scores <agent> [--days n] [--json]");
120
+ const res = await call(config, "codiedev_traces_scores", "GET", "scores", { query: { agent, days: p.flags["--days"] ?? "7" } });
121
+ if (p.bools.has("--json")) {
122
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
123
+ return;
124
+ }
125
+ if (!res.summary.length)
126
+ console.log(`No scores on ${res.agent} in the last ${p.flags["--days"] ?? 7} days.`);
127
+ for (const s of res.summary) {
128
+ const head = s.dataType === "boolean" && s.average !== null ? `${Math.round(s.average * 100)}% true`
129
+ : s.dataType === "numeric" && s.average !== null ? `avg ${Math.round(s.average * 100) / 100}`
130
+ : s.categories.map((c) => `${c.label} ${c.count}`).join(", ");
131
+ const from = [s.bySource.annotation ? `${s.bySource.annotation} people` : "", s.bySource.api ? `${s.bySource.api} your app` : "", s.bySource.judge ? `${s.bySource.judge} judge` : ""].filter(Boolean).join(", ");
132
+ console.log(`${s.name.padEnd(24)} ${head.padEnd(28)} ${s.count} scores (${from})`);
133
+ }
134
+ if (res.kinds.length)
135
+ console.log(`\nScore kinds: ${res.kinds.map((k) => `${k.name} (${k.dataType === "numeric" ? `${k.min ?? ""}–${k.max ?? ""}` : k.dataType === "boolean" ? "true/false" : k.categories.join("/")})`).join(", ")}`);
136
+ }
137
+ async function runQueue(args, config) {
138
+ const [verb, ...rest] = args;
139
+ if (verb === "list" || verb === undefined) {
140
+ const res = await call(config, "codiedev_traces_queue_list", "GET", "queues", {});
141
+ const live = res.queues.filter((q) => !q.archived);
142
+ if (!live.length)
143
+ console.log("No review queues yet. Make one in Codiedev → Traces → Review.");
144
+ for (const q of live)
145
+ console.log(`${q.name.padEnd(28)} ${String(q.pending).padStart(4)} to review ${String(q.done).padStart(4)} done ${q.scoreNames.join(", ")}`);
146
+ return;
147
+ }
148
+ if (verb === "create")
149
+ return runQueueCreate(rest, config);
150
+ if (verb !== "add")
151
+ usage("codiedev traces queue list | queue create <name> [--scores a,b] | queue add <queue> --agent <name> [--failed] [--days n] [--run id ...]");
152
+ const p = parseArgs(rest);
153
+ const queue = p.positional[0];
154
+ if (!queue || (!p.flags["--agent"] && !p.runs.length))
155
+ usage("codiedev traces queue add <queue> --agent <name> [--failed] [--days n] [--run id ...]");
156
+ const res = await call(config, "codiedev_traces_queue_add", "POST", "queue", {
157
+ body: { queue, agent: p.flags["--agent"], failed: p.bools.has("--failed"), ...(p.flags["--days"] ? { days: Number(p.flags["--days"]) } : {}), ...(p.runs.length ? { runs: p.runs } : {}) },
158
+ });
159
+ console.log(`✓ Added ${res.added} ${res.added === 1 ? "run" : "runs"} to ${res.queue}${res.skipped ? ` (${res.skipped} already there or not yours)` : ""}. Review them in Codiedev → Traces → Review.`);
160
+ }
161
+ function printJudge(agent, judge) {
162
+ if (!judge || judge === "none") {
163
+ console.log(`Automatic scoring isn't set up for ${agent}.`);
164
+ return;
165
+ }
166
+ console.log(`${agent}: automatic scoring ${judge.enabled ? "on" : "off"}`);
167
+ console.log(` scores ${judge.scoreNames.join(", ")} · ${Math.round(judge.sampleRate * 100)}% of runs, up to ${judge.dailyMaxRuns}/day · ${judge.model}`);
168
+ if (judge.judgeKey)
169
+ console.log(` billed to ${judge.judgeKey.name}${judge.judgeKey.monthlyBudgetUsd !== null ? ` ($${judge.judgeKey.monthlyBudgetUsd}/mo)` : ""} · ${judge.judgedToday} judged in 24h${judge.errorsToday ? `, ${judge.errorsToday} failed` : ""}`);
170
+ if (judge.lastError)
171
+ console.log(` last problem: ${judge.lastError}`);
172
+ }
173
+ async function runJudge(args, config) {
174
+ const p = parseArgs(args);
175
+ const agent = p.positional[0];
176
+ const help = "codiedev traces judge <agent> [--on | --off] [--scores a,b] [--instructions text] [--model id] [--sample percent] [--daily n] [--budget usd | --key cdvm_…]";
177
+ if (!agent)
178
+ usage(help);
179
+ const changing = p.bools.has("--on") || p.bools.has("--off") || Object.keys(p.flags).length > 0;
180
+ if (!changing) {
181
+ const res = await call(config, "codiedev_traces_judge", "GET", "judge", { query: { agent } });
182
+ printJudge(res.agent, res.judge);
183
+ return;
184
+ }
185
+ const res = await call(config, "codiedev_traces_judge_set", "POST", "judge", {
186
+ body: {
187
+ agent,
188
+ ...(p.bools.has("--on") ? { enabled: true } : p.bools.has("--off") ? { enabled: false } : {}),
189
+ ...(p.flags["--scores"] ? { scores: p.flags["--scores"].split(",").map((s) => s.trim()).filter(Boolean) } : {}),
190
+ ...(p.flags["--instructions"] ? { instructions: p.flags["--instructions"] } : {}),
191
+ ...(p.flags["--model"] ? { model: p.flags["--model"] } : {}),
192
+ ...(p.flags["--sample"] ? { sampleRate: Number(p.flags["--sample"]) / 100 } : {}),
193
+ ...(p.flags["--daily"] ? { dailyMaxRuns: Number(p.flags["--daily"]) } : {}),
194
+ ...(p.flags["--budget"] ? { newKeyBudgetUsd: Number(p.flags["--budget"]) } : {}),
195
+ ...(p.flags["--key"] ? { pastedKey: p.flags["--key"] } : {}),
196
+ },
197
+ });
198
+ printJudge(res.agent, res.judge);
199
+ }
200
+ async function runImport(args, config) {
201
+ const p = parseArgs(args);
202
+ const [agent, file] = p.positional;
203
+ const dataset = p.flags["--dataset"];
204
+ if (!agent || !file || !dataset)
205
+ usage("codiedev traces import <agent> <file.csv|file.jsonl> --dataset <name>");
206
+ let text;
207
+ try {
208
+ text = fs.readFileSync(path.resolve(process.cwd(), file), "utf8");
209
+ }
210
+ catch (err) {
211
+ console.error(`Couldn't read ${file}: ${err.message}`);
212
+ process.exit(1);
213
+ }
214
+ const res = await call(config, "codiedev_traces_import", "POST", "examples", { body: { agent, dataset, text } });
215
+ console.log(`✓ Imported ${res.added} ${res.added === 1 ? "example" : "examples"} into ${dataset} for ${agent}.`);
216
+ for (const e of res.errors.slice(0, 10))
217
+ console.log(` skipped${e.line ? ` line ${e.line}` : ""}: ${e.error}`);
218
+ }
219
+ async function runAddExample(args, config) {
220
+ const p = parseArgs(args);
221
+ const agent = p.positional[0];
222
+ const dataset = p.flags["--dataset"];
223
+ const input = p.flags["--input"];
224
+ if (!agent || !dataset || !input)
225
+ usage("codiedev traces add-example <agent> --dataset <name> --input <text> [--expected <text>] [--name <text>]");
226
+ await call(config, "codiedev_traces_add_example", "POST", "examples", { body: { agent, dataset, input, expected: p.flags["--expected"], name: p.flags["--name"] } });
227
+ console.log(`✓ Added an example to ${dataset} for ${agent}.`);
228
+ }
229
+ async function runVersions(args, config) {
230
+ const dataset = parseArgs(args).positional[0];
231
+ if (!dataset)
232
+ usage("codiedev traces versions <dataset>");
233
+ const res = await call(config, "codiedev_traces_versions", "GET", "versions", { query: { dataset } });
234
+ if (!res.versions.length)
235
+ console.log(`${dataset} has no saved versions. Save one with: codiedev traces save-version "${dataset}"`);
236
+ for (const v of res.versions)
237
+ console.log(`v${v.version} ${String(v.cases).padStart(4)} cases ${new Date(v.createdAt).toISOString().slice(0, 10)} +${v.added} −${v.removed} ${v.changed} edited${v.note ? ` ${v.note}` : ""}`);
238
+ if (res.unsaved)
239
+ console.log(`Unsaved since v${res.versions[0].version}: +${res.unsaved.added} −${res.unsaved.removed} ${res.unsaved.changed} edited`);
240
+ }
241
+ async function runSaveVersion(args, config) {
242
+ const p = parseArgs(args);
243
+ const dataset = p.positional[0];
244
+ if (!dataset)
245
+ usage("codiedev traces save-version <dataset> [--note text]");
246
+ const res = await call(config, "codiedev_traces_save_version", "POST", "versions", { body: { dataset, note: p.flags["--note"] } });
247
+ console.log(`✓ Saved ${dataset} as v${res.version} (${res.cases} cases). Run it later with --dataset "${dataset}" --version ${res.version}.`);
248
+ }
249
+ const usd = (n) => (n === 0 ? "$0" : n < 0.01 ? "<$0.01" : `$${n.toFixed(2)}`);
250
+ const json = (p, value) => { if (p.bools.has("--json")) {
251
+ process.stdout.write(JSON.stringify(value, null, 2) + "\n");
252
+ return true;
253
+ } return false; };
254
+ async function runOverview(args, config) {
255
+ const p = parseArgs(args);
256
+ const res = await call(config, "codiedev_traces_overview", "GET", "overview", { query: { days: p.flags["--days"] ?? "7" } });
257
+ if (json(p, res))
258
+ return;
259
+ if (!res.agents.length) {
260
+ console.log("No agents you can see yet. Connect one in Codiedev → Traces.");
261
+ return;
262
+ }
263
+ console.log(`Agents, last ${res.range}:`);
264
+ for (const a of res.agents)
265
+ console.log(` ${a.name.padEnd(28)} ${String(a.runs).padStart(6)} runs ${String(a.failedRuns).padStart(5)} failed ${usd(a.spend7dUsd).padStart(9)} 7d spend ${a.keepsPromptsDays ? `prompts ${a.keepsPromptsDays}d` : "metadata only"}${a.spike ? " spend spike" : ""}${a.budgetBlock ? " budget block" : ""}`);
266
+ if (res.issues.length) {
267
+ console.log("\nWhat's going wrong:");
268
+ for (const i of res.issues)
269
+ console.log(` ${i.label.padEnd(18)} ${String(i.runs).padStart(5)} runs ${usd(i.wastedUsd).padStart(9)} wasted ${i.agents.join(", ")}${i.exampleRun ? ` e.g. ${i.exampleRun}` : ""}`);
270
+ }
271
+ }
272
+ async function runRuns(args, config) {
273
+ const p = parseArgs(args);
274
+ const agent = p.positional[0];
275
+ if (!agent)
276
+ usage("codiedev traces runs <agent> [--failed] [--flag errors|truncated|tool_loop|context_overflow|budget_block] [--model id] [--verdict pass|fail] [--days n] [--limit n] [--json]");
277
+ const res = await call(config, "codiedev_traces_runs", "GET", "runs", {
278
+ query: { agent, days: p.flags["--days"] ?? "7", ...(p.bools.has("--failed") ? { failed: "1" } : {}), ...(p.flags["--flag"] ? { flag: p.flags["--flag"] } : {}), ...(p.flags["--model"] ? { model: p.flags["--model"] } : {}), ...(p.flags["--verdict"] ? { verdict: p.flags["--verdict"] } : {}), limit: p.flags["--limit"] ?? "50" },
279
+ });
280
+ if (json(p, res))
281
+ return;
282
+ console.log(`${res.total} ${res.total === 1 ? "run" : "runs"} for ${res.agent}, last ${res.range}${res.total > res.runs.length ? ` (newest ${res.runs.length})` : ""}:`);
283
+ for (const r of res.runs)
284
+ console.log(` ${r.startedAt.slice(0, 16).replace("T", " ")} ${r.status === "failed" ? "FAIL" : " ok "} ${r.runId.padEnd(24)} ${String(r.steps).padStart(3)} calls ${usd(r.costUsd).padStart(8)} ${r.model ?? ""}${r.flags.length ? ` [${r.flags.join(", ")}]` : ""}${r.verdict ? ` marked ${r.verdict}` : ""}`);
285
+ if (res.runs.length)
286
+ console.log(`\nOpen one: codiedev traces run ${res.runs[0].runId} --agent "${res.agent}"`);
287
+ }
288
+ async function runRun(args, config) {
289
+ const p = parseArgs(args);
290
+ const run = p.positional[0];
291
+ if (!run)
292
+ usage("codiedev traces run <run> [--agent name] [--json]");
293
+ const res = await call(config, "codiedev_traces_run", "GET", "run", { query: { run, ...(p.flags["--agent"] ? { agent: p.flags["--agent"] } : {}) } });
294
+ if (json(p, res))
295
+ return;
296
+ const r = res.run;
297
+ console.log(`${r.title} · ${r.id}`);
298
+ console.log(`${new Date(r.startedAt).toISOString().slice(0, 16).replace("T", " ")} · ${r.status === "failed" ? "FAILED" : "ok"} · ${Math.round(r.durationMs / 100) / 10}s · ${usd(r.costUsd)}${r.flags.length ? ` · ${r.flags.join(", ")}` : ""}`);
299
+ if (r.diagnosis)
300
+ console.log(`\nWhat went wrong: ${r.diagnosis.title}\n ${r.diagnosis.why}\n\nFix (for your coding agent):\n${r.diagnosis.fix.split("\n").map((l) => ` ${l}`).join("\n")}`);
301
+ if (r.annotation)
302
+ console.log(`\nMarked ${r.annotation.verdict} by ${r.annotation.by}${r.annotation.reason ? `: ${r.annotation.reason}` : ""}`);
303
+ if (res.scores.length)
304
+ console.log(`\nScores: ${res.scores.map((s) => `${s.name} ${s.text}${s.step ? ` (step ${s.step})` : ""} by ${s.by ?? s.source}${s.comment ? ` "${s.comment}"` : ""}`).join("; ")}`);
305
+ console.log("\nSteps:");
306
+ for (const s of r.spans.filter((x) => x.kind !== "run")) {
307
+ console.log(` ${s.kind === "tool" ? "tool" : "call"} ${s.name} ${Math.round(s.durationMs)}ms${s.costUsd !== undefined ? ` ${usd(s.costUsd)}` : ""}${s.finishReason ? ` finish: ${s.finishReason}` : ""}${s.statusCode && s.statusCode >= 400 ? ` HTTP ${s.statusCode}` : ""}${s.flag ? ` [${s.flag}]` : ""}${s.note ? ` ${s.note}` : ""}`);
308
+ if (s.input)
309
+ console.log(` prompt: ${s.input.replace(/\s+/g, " ").slice(0, 300)}`);
310
+ if (s.output)
311
+ console.log(` reply: ${s.output.replace(/\s+/g, " ").slice(0, 300)}`);
312
+ }
313
+ if (!r.bodiesVisible)
314
+ console.log("\n(Prompts and replies are shown only to the agent's maintainers.)");
315
+ }
316
+ async function runScoreKinds(args, config) {
317
+ const [verb, ...rest] = args;
318
+ if (verb === "add") {
319
+ const p = parseArgs(rest);
320
+ const name = p.positional[0];
321
+ const type = p.flags["--type"];
322
+ if (!name || !type)
323
+ usage("codiedev traces score-kinds add <name> --type number|categories|boolean [--min n --max n] [--categories a,b,c] [--description text]");
324
+ const dataType = type === "number" || type === "numeric" ? "numeric" : type === "categories" || type === "categorical" ? "categorical" : type === "boolean" || type === "bool" ? "boolean" : type;
325
+ await call(config, "codiedev_traces_score_kind_add", "POST", "score-kinds", {
326
+ body: { name, type: dataType, ...(p.flags["--min"] ? { min: Number(p.flags["--min"]) } : {}), ...(p.flags["--max"] ? { max: Number(p.flags["--max"]) } : {}), ...(p.flags["--categories"] ? { categories: p.flags["--categories"].split(",").map((c) => c.trim()) } : {}), ...(p.flags["--description"] ? { description: p.flags["--description"] } : {}) },
327
+ });
328
+ console.log(`✓ Added score kind ${name}.`);
329
+ return;
330
+ }
331
+ const p = parseArgs(verb === undefined || verb === "list" ? rest : args);
332
+ const res = await call(config, "codiedev_traces_score_kinds", "GET", "score-kinds", {});
333
+ if (json(p, res))
334
+ return;
335
+ const live = res.kinds.filter((k) => !k.archived);
336
+ if (!live.length)
337
+ console.log("No score kinds yet. Add one: codiedev traces score-kinds add helpfulness --type number --min 1 --max 5");
338
+ for (const k of live)
339
+ console.log(` ${k.name.padEnd(24)} ${k.dataType === "numeric" ? `number ${k.min ?? ""}–${k.max ?? ""}` : k.dataType === "boolean" ? "true / false" : k.categories.join(" / ")}${k.description ? ` ${k.description}` : ""}`);
340
+ }
341
+ async function runQueueCreate(args, config) {
342
+ const p = parseArgs(args);
343
+ const name = p.positional[0];
344
+ if (!name)
345
+ usage("codiedev traces queue create <name> [--scores a,b] [--description text]");
346
+ await call(config, "codiedev_traces_queue_create", "POST", "queues", { body: { name, scores: (p.flags["--scores"] ?? "").split(",").map((s) => s.trim()).filter(Boolean), ...(p.flags["--description"] ? { description: p.flags["--description"] } : {}) } });
347
+ console.log(`✓ Created review queue ${name}. Add runs: codiedev traces queue add "${name}" --agent <name> --failed`);
348
+ }
package/dist/configDir.js CHANGED
@@ -34,16 +34,6 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.codiedevStateDir = codiedevStateDir;
37
- // Single source of truth for where the CLI's config/state lives on disk.
38
- //
39
- // Defaults to ~/.codiedev. The desktop app sets CODIEDEV_CONFIG_DIR to
40
- // ~/.codiedev-desktop so a desktop session never touches the user's real
41
- // prod config — env-based (not a flag) so detached capture-finish/upload
42
- // children inherit the override automatically.
43
- //
44
- // Deliberately dependency-free (only node:path/os) so it can be imported
45
- // by both utils.ts and modules utils.ts itself imports (e.g. captureLog.ts)
46
- // without creating a circular import.
47
37
  const path = __importStar(require("path"));
48
38
  const os = __importStar(require("os"));
49
39
  const CONFIG_DIR = process.env.CODIEDEV_CONFIG_DIR?.trim()
package/dist/connect.js CHANGED
@@ -39,36 +39,19 @@ 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 fs = __importStar(require("fs"));
43
42
  const path = __importStar(require("path"));
44
43
  const utils_1 = require("./utils");
45
44
  const connectFlow_1 = require("./connectFlow");
46
45
  const version_1 = require("./version");
47
46
  const upgradeNudge_1 = require("./upgradeNudge");
48
47
  const shared_1 = require("./commands/shared");
49
- const securityInstall_1 = require("./securityInstall");
50
- const securityPolicy_1 = require("./securityPolicy");
51
- const securityFeature_1 = require("./securityFeature");
52
- // cli.codiedev.com is a Convex custom domain on the prod deployment; the
53
- // underlying judicious-falcon-861.convex.site URL keeps serving, so configs
54
- // written by older CLI versions stay valid without a re-connect.
48
+ const harnessDirs_1 = require("./harnessDirs");
55
49
  const BACKEND_URL = process.env.CODIEDEV_URL || "https://cli.codiedev.com";
56
- /**
57
- * Reads a line from stdin without echoing the typed/pasted characters —
58
- * for tokens, passwords, anything that shouldn't end up in terminal
59
- * scrollback or screenshots. Echoes `*` per character so the user gets
60
- * visual feedback that input is being received.
61
- *
62
- * Falls back to the regular `prompt()` if stdin isn't a TTY (e.g., piped
63
- * input in CI). Without a TTY there's no echo to suppress anyway, and
64
- * raw mode would error.
65
- */
66
50
  function promptHidden(question) {
67
51
  return new Promise((resolve) => {
68
52
  const stdin = process.stdin;
69
53
  const stdout = process.stdout;
70
54
  if (!stdin.isTTY) {
71
- // CI / piped input — no terminal to mute. Fall back to readline.
72
55
  const rl = readline.createInterface({ input: stdin, output: stdout });
73
56
  rl.question(question, (answer) => {
74
57
  rl.close();
@@ -85,23 +68,18 @@ function promptHidden(question) {
85
68
  };
86
69
  const onData = (chunk) => {
87
70
  const key = chunk.toString("utf8");
88
- // Iterate so a single `chunk` containing a multi-char paste still
89
- // masks each character individually.
90
71
  for (const ch of key) {
91
- // Ctrl+C — abort like a normal terminal interrupt.
92
72
  if (ch === "") {
93
73
  cleanup();
94
74
  stdout.write("\n");
95
75
  process.exit(130);
96
76
  }
97
- // Enter — finalize.
98
77
  if (ch === "\r" || ch === "\n") {
99
78
  cleanup();
100
79
  stdout.write("\n");
101
80
  resolve(buf.trim());
102
81
  return;
103
82
  }
104
- // Backspace / DEL — erase one masked char.
105
83
  if (ch === "" || ch === "\b") {
106
84
  if (buf.length > 0) {
107
85
  buf = buf.slice(0, -1);
@@ -109,7 +87,6 @@ function promptHidden(question) {
109
87
  }
110
88
  continue;
111
89
  }
112
- // Ignore other control bytes (escape sequences from arrow keys, etc.)
113
90
  if (ch.charCodeAt(0) < 0x20)
114
91
  continue;
115
92
  buf += ch;
@@ -165,11 +142,6 @@ function postJson(url, body, extraHeaders = {}) {
165
142
  });
166
143
  }
167
144
  async function runConnect(args = []) {
168
- // `--force` (or `-f`) re-prompts for a token even if `~/.codiedev/config.json`
169
- // already has one. Default behavior reuses the saved token so users can
170
- // re-run `connect` (e.g., after installing Claude Code) without having to
171
- // mint a fresh token from the portal — which is what bit Sonifi's first
172
- // engineer when he interpreted "no visible token" as "the old one is gone".
173
145
  const force = args.includes("--force") || args.includes("-f");
174
146
  console.log("\nWelcome to Codiedev CLI\n");
175
147
  await (0, upgradeNudge_1.maybePrintUpgradeNudge)();
@@ -183,8 +155,6 @@ async function runConnect(args = []) {
183
155
  console.log(`Reusing API token from ~/.codiedev/config.json (run with --force to use a new one).\n`);
184
156
  }
185
157
  else {
186
- // Hidden prompt — masks the token with `*` as it's typed/pasted so it
187
- // doesn't end up in terminal scrollback or screenshots.
188
158
  token = await promptHidden("Enter your Codiedev API token: ");
189
159
  if (!token) {
190
160
  console.error("Error: API token is required.");
@@ -202,10 +172,8 @@ async function runConnect(args = []) {
202
172
  console.error(`\nError: Failed to validate token — ${err.message}`);
203
173
  process.exit(1);
204
174
  }
205
- // Extract fields from response
206
175
  const companyId = responseData.companyId;
207
176
  const companyName = responseData.companyName;
208
- const agentSecurityEnabled = responseData.agentSecurityEnabled === true;
209
177
  const repos = responseData.repos ?? [];
210
178
  if (!companyId || !companyName) {
211
179
  console.error("\nError: Invalid response from server. Token may be invalid.");
@@ -218,7 +186,6 @@ async function runConnect(args = []) {
218
186
  repos,
219
187
  lastSynced: new Date().toISOString(),
220
188
  backendUrl: BACKEND_URL,
221
- agentSecurityEnabled,
222
189
  deviceId: saved?.deviceId || crypto.randomUUID(),
223
190
  deviceName: saved?.deviceName || os.hostname(),
224
191
  captureIgnoredPaths: saved?.captureIgnoredPaths ?? [],
@@ -230,15 +197,7 @@ async function runConnect(args = []) {
230
197
  console.error(`\nError: Failed to save config — ${err.message}`);
231
198
  process.exit(1);
232
199
  }
233
- // Once we have a valid token + config, every subsequent step posts a
234
- // per-step row to /api/telemetry/install-event so the admin page can show
235
- // a timeline when a customer says "it connected but it doesn't work."
236
- // Fire-and-forget — never blocks the connect flow.
237
200
  (0, shared_1.recordInstallEvent)(config, { step: "started", ok: true });
238
- // One-way device status sync. Local config remains authoritative: a network
239
- // failure here never removes or weakens an ignored path. This also registers
240
- // a freshly connected device with an empty list so the portal can distinguish
241
- // "connected, no exclusions" from "old CLI has never reported status".
242
201
  try {
243
202
  await postJson(`${BACKEND_URL}/api/cli/capture-exclusions`, {
244
203
  deviceId: config.deviceId,
@@ -249,17 +208,6 @@ async function runConnect(args = []) {
249
208
  catch (err) {
250
209
  console.warn(`Warning: Local capture settings are active, but portal status did not sync — ${err.message}`);
251
210
  }
252
- // Migration: strip MCP server entries written by pre-CLI-only versions
253
- // of `codiedev connect`. These pointed at `npx codiedev-mcp`, a binary
254
- // that was removed in 0.3.4 and that 0.7.11+ no longer ships. Without
255
- // cleanup, customers upgrading from any prior version see persistent
256
- // "MCP server failed to start" errors in their agent UIs even though
257
- // the CLI works fine. Each helper is idempotent and a no-op when the
258
- // relevant config file doesn't exist.
259
- //
260
- // Each call is wrapped because the user's upgrade path matters more
261
- // than the cleanup. A locked / wrong-owner config file (rare but real)
262
- // shouldn't block the install loop or strand them on an old version.
263
211
  for (const [label, fn] of [
264
212
  ["Claude Code", utils_1.cleanupClaudeCodeMcp],
265
213
  ["Codex", utils_1.cleanupCodexMcp],
@@ -278,29 +226,16 @@ async function runConnect(args = []) {
278
226
  const hasCodex = (0, utils_1.codexInstalled)();
279
227
  const hasCursor = (0, utils_1.cursorInstalled)();
280
228
  const hasOpenCode = (0, utils_1.openCodeInstalled)();
229
+ const hasCopilot = (0, utils_1.copilotInstalled)();
230
+ const hasPi = (0, utils_1.piInstalled)();
281
231
  (0, shared_1.recordInstallEvent)(config, { step: "detect", target: "claude-code", ok: hasClaude });
282
232
  (0, shared_1.recordInstallEvent)(config, { step: "detect", target: "codex", ok: hasCodex });
283
233
  (0, shared_1.recordInstallEvent)(config, { step: "detect", target: "cursor", ok: hasCursor });
284
234
  (0, shared_1.recordInstallEvent)(config, { step: "detect", target: "opencode", ok: hasOpenCode });
235
+ (0, shared_1.recordInstallEvent)(config, { step: "detect", target: "copilot", ok: hasCopilot });
236
+ (0, shared_1.recordInstallEvent)(config, { step: "detect", target: "pi", ok: hasPi });
285
237
  const installed = [];
286
- // Machine-readable target keys reported back to the backend via
287
- // /api/cli/markInstalled so the portal's "Connected" state reflects
288
- // what's actually wired up on this machine, not just "token validated."
289
238
  const installedTargets = [];
290
- const home = os.homedir();
291
- const securityConfigPaths = [
292
- path.join(home, ".claude", "settings.json"),
293
- path.join(home, ".codex", "hooks.json"),
294
- path.join(home, ".cursor", "hooks.json"),
295
- path.join(home, ".config", "opencode", "plugins", "codiedev.js"),
296
- path.join(home, ".codex", "config.toml"),
297
- ];
298
- // Snapshot before any hook update. Rollback is intentionally not automatic:
299
- // an administrator can inspect these 0600 copies before restoring them.
300
- const securitySnapshot = (0, securityInstall_1.createSecurityInstallSnapshot)(securityConfigPaths);
301
- // Wrap each per-target write so we emit one install_target row each. The
302
- // existing user-visible behavior (console.warn on failure, continue) is
303
- // unchanged — telemetry just observes the outcome.
304
239
  const runInstall = (target, fn, label, targetKey) => {
305
240
  try {
306
241
  fn();
@@ -320,56 +255,26 @@ async function runConnect(args = []) {
320
255
  }
321
256
  };
322
257
  if (hasClaude) {
323
- runInstall("claude-code-hook", () => (0, utils_1.installHook)(agentSecurityEnabled), "Claude Code SessionEnd (capture) + UserPromptSubmit (skill discovery) + Stop (auto-backup) hooks (~/.claude/settings.json)", "claudeCode-hook");
324
- runInstall("claude-code-instructions", utils_1.installClaudeCodeInstructions, "Claude Code agent instructions (~/.claude/CLAUDE.md)", "claudeCode-instructions");
258
+ 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");
259
+ 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");
325
260
  }
326
261
  if (hasCodex) {
327
- runInstall("codex-hook", () => (0, utils_1.installCodexHook)(agentSecurityEnabled), "Codex Stop (capture + auto-backup) hooks (~/.codex/hooks.json)", "codex-hook");
328
- runInstall("codex-instructions", utils_1.installCodexInstructions, "Codex agent instructions (~/.codex/AGENTS.md)", "codex-instructions");
262
+ 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");
263
+ runInstall("codex-instructions", utils_1.installCodexInstructions, `Codex agent instructions (${(0, harnessDirs_1.displayPath)(path.join((0, harnessDirs_1.codexHome)(), "AGENTS.md"))})`, "codex-instructions");
329
264
  }
330
265
  if (hasCursor) {
331
- runInstall("cursor-hook", () => (0, utils_1.installCursorHook)(agentSecurityEnabled), "Cursor sessionStart + prompt security + stop backup + sessionEnd capture hooks (~/.cursor/hooks.json)", "cursor-hook");
266
+ runInstall("cursor-hook", utils_1.installCursorHook, "Cursor sessionStart + stop backup + sessionEnd capture hooks (~/.cursor/hooks.json)", "cursor-hook");
332
267
  runInstall("cursor-instructions", utils_1.installCursorInstructions, "Cursor agent instructions (~/.cursor/rules/codiedev.mdc)", "cursor-instructions");
333
268
  }
334
- // Always stage the adapter. It is dormant until OpenCode starts, which lets
335
- // a user connect Claude Code today and install the Codie harness tomorrow
336
- // without needing a second setup ritual.
337
- runInstall("opencode-capture-adapter", () => (0, utils_1.installOpenCodeCapturePlugin)(agentSecurityEnabled), "OpenCode session capture adapter (~/.config/opencode/plugins/codiedev.js)", "opencode-capture");
338
- // Record the exact installed hook bytes and the pre-update rollback files.
339
- // This supplies health/integrity checks without requiring a package publish
340
- // or trusting whichever `node` happens to be first on PATH later.
341
- try {
342
- const hookScriptPath = path.join(__dirname, "hook.js");
343
- if (agentSecurityEnabled && fs.existsSync(hookScriptPath)) {
344
- const targets = [];
345
- if (installedTargets.includes("claudeCode-hook"))
346
- targets.push({ surface: "claude-code", configPath: securityConfigPaths[0] });
347
- if (installedTargets.includes("codex-hook"))
348
- targets.push({ surface: "codex", configPath: securityConfigPaths[1] });
349
- if (installedTargets.includes("cursor-hook"))
350
- targets.push({ surface: "cursor", configPath: securityConfigPaths[2] });
351
- if (installedTargets.includes("opencode-capture"))
352
- targets.push({ surface: "codie-harness", configPath: securityConfigPaths[3] });
353
- (0, securityInstall_1.writeSecurityInstallManifest)({ hookScriptPath, snapshot: securitySnapshot, targets });
354
- }
269
+ if (hasCopilot) {
270
+ runInstall("copilot-hook", utils_1.installCopilotHook, `GitHub Copilot (VS Code + CLI) sessionStart + agentStop backup + sessionEnd capture hooks (${(0, utils_1.copilotHooksPath)()})`, "copilot-hook");
271
+ runInstall("copilot-instructions", utils_1.installCopilotInstructions, "GitHub Copilot CLI team artifact instructions", "copilot-instructions");
355
272
  }
356
- catch (err) {
357
- console.warn(`Warning: Security hooks installed, but integrity manifest could not be written — ${err.message}`);
273
+ runInstall("pi-extension", utils_1.installPiExtension, `pi session start + skill discovery + capture extension (${(0, harnessDirs_1.displayPath)((0, utils_1.piExtensionPath)())})`, "pi-extension");
274
+ if (hasPi) {
275
+ runInstall("pi-instructions", utils_1.installPiInstructions, `pi agent instructions (${(0, harnessDirs_1.displayPath)((0, utils_1.piInstructionsPath)())})`, "pi-instructions");
358
276
  }
359
- // Prime the local cache after installation. Hooks read this file only, so
360
- // an endpoint decision never depends on live network latency.
361
- if (agentSecurityEnabled) {
362
- try {
363
- await (0, securityPolicy_1.syncEndpointSecurityPolicy)(config);
364
- }
365
- catch (err) {
366
- console.warn(`Warning: Agent-security policy will use safe defaults until sync succeeds — ${err.message}`);
367
- }
368
- }
369
- // Tell the backend which targets we wired up so the portal's onboarding
370
- // card flips to "Connected" only when something actually installed —
371
- // not on bare token validation. Best-effort: a network failure here
372
- // doesn't undo the local install, and `codiedev doctor` still works.
277
+ 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");
373
278
  if (installedTargets.length > 0) {
374
279
  try {
375
280
  await postJson(`${BACKEND_URL}/api/cli/markInstalled`, {
@@ -388,7 +293,7 @@ async function runConnect(args = []) {
388
293
  });
389
294
  }
390
295
  }
391
- if (!hasClaude && !hasCodex && !hasCursor && !hasOpenCode) {
296
+ if (!hasClaude && !hasCodex && !hasCursor && !hasOpenCode && !hasCopilot && !hasPi) {
392
297
  console.warn("\nNo existing AI client detected; the Codie/OpenCode adapter is ready for a later install.");
393
298
  console.warn("If you just installed Claude Code, launch it once (so ~/.claude is created),");
394
299
  console.warn("then re-run `npx codiedev connect` to wire up the capture hook.");
@@ -404,8 +309,6 @@ async function runConnect(args = []) {
404
309
  }
405
310
  console.log();
406
311
  console.log("Run `codiedev doctor` to verify everything's wired up.");
407
- if ((0, securityFeature_1.isAgentSecurityEnabled)(config)) {
408
- console.log("Run `codiedev security pilot` to validate blocking safely.");
409
- }
312
+ console.log("If `codiedev` is not on PATH, run `npx codiedev@latest doctor` instead.");
410
313
  console.log();
411
314
  }
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- // Pure helper for `npx codiedev connect` — decides where the API token
3
- // comes from. Splitting this out lets us TDD the policy (re-use vs. re-prompt)
4
- // without touching readline or fs at all.
5
- //
6
- // Motivation: Jackson hit a confusing flow where he had a working token in
7
- // `~/.codiedev/config.json`, re-ran `connect` (to pick up Claude Code that
8
- // he'd just installed), and was forced to paste a token again. Since the
9
- // portal only displays the plaintext on creation, his only option was to
10
- // generate a new one — leaving him thinking the old one had been lost.
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.resolveConnectToken = resolveConnectToken;
13
4
  function resolveConnectToken(input) {