pakhale 0.1.0

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/cli.js ADDED
@@ -0,0 +1,2037 @@
1
+ #!/usr/bin/env node
2
+ import { copyFile, lstat, mkdir, readFile, readdir, readlink, rename, rm, symlink, writeFile } from "node:fs/promises";
3
+ import { basename, dirname, join, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { homedir } from "node:os";
6
+ import { parseArgs, styleText } from "node:util";
7
+ import process$1, { stdin, stdout } from "node:process";
8
+ import l__default from "node:readline";
9
+ import { spawn } from "node:child_process";
10
+
11
+ //#region rolldown:runtime
12
+ var __create = Object.create;
13
+ var __defProp = Object.defineProperty;
14
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
15
+ var __getOwnPropNames = Object.getOwnPropertyNames;
16
+ var __getProtoOf = Object.getPrototypeOf;
17
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
18
+ var __commonJS = (cb, mod) => function() {
19
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
20
+ };
21
+ var __copyProps = (to, from, except, desc) => {
22
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i$1 = 0, n$2 = keys.length, key; i$1 < n$2; i$1++) {
23
+ key = keys[i$1];
24
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
25
+ get: ((k) => from[k]).bind(null, key),
26
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
27
+ });
28
+ }
29
+ return to;
30
+ };
31
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
32
+ value: mod,
33
+ enumerable: true
34
+ }) : target, mod));
35
+
36
+ //#endregion
37
+ //#region node_modules/picocolors/picocolors.js
38
+ var require_picocolors = /* @__PURE__ */ __commonJS({ "node_modules/picocolors/picocolors.js": ((exports, module) => {
39
+ let p = process || {}, argv = p.argv || [], env = p.env || {};
40
+ let isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
41
+ let formatter = (open, close, replace = open) => (input) => {
42
+ let string = "" + input, index = string.indexOf(close, open.length);
43
+ return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
44
+ };
45
+ let replaceClose = (string, close, replace, index) => {
46
+ let result = "", cursor$3 = 0;
47
+ do {
48
+ result += string.substring(cursor$3, index) + replace;
49
+ cursor$3 = index + close.length;
50
+ index = string.indexOf(close, cursor$3);
51
+ } while (~index);
52
+ return result + string.substring(cursor$3);
53
+ };
54
+ let createColors = (enabled = isColorSupported) => {
55
+ let f = enabled ? formatter : () => String;
56
+ return {
57
+ isColorSupported: enabled,
58
+ reset: f("\x1B[0m", "\x1B[0m"),
59
+ bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
60
+ dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
61
+ italic: f("\x1B[3m", "\x1B[23m"),
62
+ underline: f("\x1B[4m", "\x1B[24m"),
63
+ inverse: f("\x1B[7m", "\x1B[27m"),
64
+ hidden: f("\x1B[8m", "\x1B[28m"),
65
+ strikethrough: f("\x1B[9m", "\x1B[29m"),
66
+ black: f("\x1B[30m", "\x1B[39m"),
67
+ red: f("\x1B[31m", "\x1B[39m"),
68
+ green: f("\x1B[32m", "\x1B[39m"),
69
+ yellow: f("\x1B[33m", "\x1B[39m"),
70
+ blue: f("\x1B[34m", "\x1B[39m"),
71
+ magenta: f("\x1B[35m", "\x1B[39m"),
72
+ cyan: f("\x1B[36m", "\x1B[39m"),
73
+ white: f("\x1B[37m", "\x1B[39m"),
74
+ gray: f("\x1B[90m", "\x1B[39m"),
75
+ bgBlack: f("\x1B[40m", "\x1B[49m"),
76
+ bgRed: f("\x1B[41m", "\x1B[49m"),
77
+ bgGreen: f("\x1B[42m", "\x1B[49m"),
78
+ bgYellow: f("\x1B[43m", "\x1B[49m"),
79
+ bgBlue: f("\x1B[44m", "\x1B[49m"),
80
+ bgMagenta: f("\x1B[45m", "\x1B[49m"),
81
+ bgCyan: f("\x1B[46m", "\x1B[49m"),
82
+ bgWhite: f("\x1B[47m", "\x1B[49m"),
83
+ blackBright: f("\x1B[90m", "\x1B[39m"),
84
+ redBright: f("\x1B[91m", "\x1B[39m"),
85
+ greenBright: f("\x1B[92m", "\x1B[39m"),
86
+ yellowBright: f("\x1B[93m", "\x1B[39m"),
87
+ blueBright: f("\x1B[94m", "\x1B[39m"),
88
+ magentaBright: f("\x1B[95m", "\x1B[39m"),
89
+ cyanBright: f("\x1B[96m", "\x1B[39m"),
90
+ whiteBright: f("\x1B[97m", "\x1B[39m"),
91
+ bgBlackBright: f("\x1B[100m", "\x1B[49m"),
92
+ bgRedBright: f("\x1B[101m", "\x1B[49m"),
93
+ bgGreenBright: f("\x1B[102m", "\x1B[49m"),
94
+ bgYellowBright: f("\x1B[103m", "\x1B[49m"),
95
+ bgBlueBright: f("\x1B[104m", "\x1B[49m"),
96
+ bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
97
+ bgCyanBright: f("\x1B[106m", "\x1B[49m"),
98
+ bgWhiteBright: f("\x1B[107m", "\x1B[49m")
99
+ };
100
+ };
101
+ module.exports = createColors();
102
+ module.exports.createColors = createColors;
103
+ }) });
104
+
105
+ //#endregion
106
+ //#region config.ts
107
+ var import_picocolors$3 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
108
+ const config = {
109
+ agents: ["claude-code", "opencode"],
110
+ marketplaces: {
111
+ "claude-plugins-official": {
112
+ repo: "anthropics/claude-plugins-official",
113
+ builtin: true
114
+ },
115
+ plannotator: { repo: "backnotprop/plannotator" },
116
+ impeccable: { repo: "pbakaus/impeccable" }
117
+ },
118
+ extensions: [
119
+ {
120
+ name: "context7",
121
+ deliver: {
122
+ "claude-code": {
123
+ via: "claude-plugin",
124
+ marketplace: "claude-plugins-official",
125
+ plugin: "context7"
126
+ },
127
+ opencode: {
128
+ via: "mcp",
129
+ server: {
130
+ transport: "stdio",
131
+ command: [
132
+ "npx",
133
+ "-y",
134
+ "@upstash/context7-mcp"
135
+ ]
136
+ }
137
+ }
138
+ }
139
+ },
140
+ {
141
+ name: "mattpocock-skills",
142
+ deliver: {
143
+ "claude-code": {
144
+ via: "claude-plugin",
145
+ marketplace: "claude-plugins-official",
146
+ plugin: "mattpocock-skills"
147
+ },
148
+ opencode: {
149
+ via: "skills",
150
+ repo: "mattpocock/skills"
151
+ }
152
+ }
153
+ },
154
+ {
155
+ name: "plannotator",
156
+ deliver: {
157
+ "claude-code": {
158
+ via: "claude-plugin",
159
+ marketplace: "plannotator",
160
+ plugin: "plannotator"
161
+ },
162
+ opencode: {
163
+ via: "opencode-plugin",
164
+ package: "@plannotator/opencode@latest"
165
+ }
166
+ }
167
+ },
168
+ {
169
+ name: "impeccable",
170
+ deliver: {
171
+ "claude-code": {
172
+ via: "claude-plugin",
173
+ marketplace: "impeccable",
174
+ plugin: "impeccable"
175
+ },
176
+ opencode: {
177
+ via: "skills",
178
+ repo: "pbakaus/impeccable",
179
+ skills: ["impeccable"]
180
+ }
181
+ }
182
+ },
183
+ {
184
+ name: "vercel-agent-skills",
185
+ deliver: { all: {
186
+ via: "skills",
187
+ repo: "vercel-labs/agent-skills",
188
+ skills: ["vercel-react-best-practices", "vercel-composition-patterns"]
189
+ } }
190
+ },
191
+ {
192
+ name: "gh-stack",
193
+ deliver: { all: {
194
+ via: "skills",
195
+ repo: "github/gh-stack",
196
+ skills: ["gh-stack"]
197
+ } }
198
+ }
199
+ ],
200
+ authoredSkillsDir: "skills",
201
+ instructionsFile: "assets/instructions/AGENTS.md",
202
+ claudeCode: {
203
+ statuslineScript: "assets/statusline/claude-code.sh",
204
+ autoCompactWindow: 25e4,
205
+ tui: "fullscreen",
206
+ cleanupPeriodDays: 14,
207
+ voice: true,
208
+ autoDream: false,
209
+ agentPushNotifications: true,
210
+ permissions: {
211
+ defaultMode: "auto",
212
+ skipDangerousModePrompt: true,
213
+ skipAutoPrompt: true
214
+ }
215
+ }
216
+ };
217
+
218
+ //#endregion
219
+ //#region src/util/log.ts
220
+ const log = {
221
+ agent: (s) => console.log(`\n${import_picocolors$3.default.bold(import_picocolors$3.default.magenta(`■ ${s}`))}`),
222
+ section: (s) => console.log(`\n${import_picocolors$3.default.bold(import_picocolors$3.default.cyan(`▸ ${s}`))}`),
223
+ ok: (s) => console.log(` ${import_picocolors$3.default.green("✓")} ${s}`),
224
+ skip: (s) => console.log(` ${import_picocolors$3.default.dim("·")} ${import_picocolors$3.default.dim(s)}`),
225
+ warn: (s) => console.log(` ${import_picocolors$3.default.yellow("!")} ${s}`),
226
+ fail: (s) => console.log(` ${import_picocolors$3.default.red("✗")} ${s}`),
227
+ plan: (s) => console.log(` ${import_picocolors$3.default.yellow("would")} ${s}`),
228
+ info: (s) => console.log(` ${import_picocolors$3.default.dim(s)}`)
229
+ };
230
+
231
+ //#endregion
232
+ //#region node_modules/fast-string-truncated-width/dist/utils.js
233
+ const getCodePointsLength = (() => {
234
+ const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
235
+ return (input) => {
236
+ let surrogatePairsNr = 0;
237
+ SURROGATE_PAIR_RE.lastIndex = 0;
238
+ while (SURROGATE_PAIR_RE.test(input)) surrogatePairsNr += 1;
239
+ return input.length - surrogatePairsNr;
240
+ };
241
+ })();
242
+ const isFullWidth = (x) => {
243
+ return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
244
+ };
245
+ const isWideNotCJKTNotEmoji = (x) => {
246
+ return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
247
+ };
248
+
249
+ //#endregion
250
+ //#region node_modules/fast-string-truncated-width/dist/index.js
251
+ const ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
252
+ const CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
253
+ const CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/uy;
254
+ const TAB_RE = /\t{1,1000}/y;
255
+ const EMOJI_RE = /[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/uy;
256
+ const LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
257
+ const MODIFIER_RE = /\p{M}+/gu;
258
+ const NO_TRUNCATION$1 = {
259
+ limit: Infinity,
260
+ ellipsis: ""
261
+ };
262
+ const getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
263
+ const LIMIT = truncationOptions.limit ?? Infinity;
264
+ const ELLIPSIS = truncationOptions.ellipsis ?? "";
265
+ const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION$1, widthOptions).width : 0);
266
+ const ANSI_WIDTH = 0;
267
+ const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
268
+ const TAB_WIDTH = widthOptions.tabWidth ?? 8;
269
+ const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
270
+ const FULL_WIDTH_WIDTH = 2;
271
+ const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
272
+ const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
273
+ const PARSE_BLOCKS = [
274
+ [LATIN_RE, REGULAR_WIDTH],
275
+ [ANSI_RE, ANSI_WIDTH],
276
+ [CONTROL_RE, CONTROL_WIDTH],
277
+ [TAB_RE, TAB_WIDTH],
278
+ [EMOJI_RE, EMOJI_WIDTH],
279
+ [CJKT_WIDE_RE, WIDE_WIDTH]
280
+ ];
281
+ let indexPrev = 0;
282
+ let index = 0;
283
+ let length = input.length;
284
+ let lengthExtra = 0;
285
+ let truncationEnabled = false;
286
+ let truncationIndex = length;
287
+ let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
288
+ let unmatchedStart = 0;
289
+ let unmatchedEnd = 0;
290
+ let width = 0;
291
+ let widthExtra = 0;
292
+ outer: while (true) {
293
+ if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
294
+ const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
295
+ lengthExtra = 0;
296
+ for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
297
+ const codePoint = char.codePointAt(0) || 0;
298
+ if (isFullWidth(codePoint)) widthExtra = FULL_WIDTH_WIDTH;
299
+ else if (isWideNotCJKTNotEmoji(codePoint)) widthExtra = WIDE_WIDTH;
300
+ else widthExtra = REGULAR_WIDTH;
301
+ if (width + widthExtra > truncationLimit) truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
302
+ if (width + widthExtra > LIMIT) {
303
+ truncationEnabled = true;
304
+ break outer;
305
+ }
306
+ lengthExtra += char.length;
307
+ width += widthExtra;
308
+ }
309
+ unmatchedStart = unmatchedEnd = 0;
310
+ }
311
+ if (index >= length) break outer;
312
+ for (let i$1 = 0, l = PARSE_BLOCKS.length; i$1 < l; i$1++) {
313
+ const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i$1];
314
+ BLOCK_RE.lastIndex = index;
315
+ if (BLOCK_RE.test(input)) {
316
+ lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
317
+ widthExtra = lengthExtra * BLOCK_WIDTH;
318
+ if (width + widthExtra > truncationLimit) truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
319
+ if (width + widthExtra > LIMIT) {
320
+ truncationEnabled = true;
321
+ break outer;
322
+ }
323
+ width += widthExtra;
324
+ unmatchedStart = indexPrev;
325
+ unmatchedEnd = index;
326
+ index = indexPrev = BLOCK_RE.lastIndex;
327
+ continue outer;
328
+ }
329
+ }
330
+ index += 1;
331
+ }
332
+ return {
333
+ width: truncationEnabled ? truncationLimit : width,
334
+ index: truncationEnabled ? truncationIndex : length,
335
+ truncated: truncationEnabled,
336
+ ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
337
+ };
338
+ };
339
+ var dist_default$1 = getStringTruncatedWidth;
340
+
341
+ //#endregion
342
+ //#region node_modules/fast-string-width/dist/index.js
343
+ const NO_TRUNCATION = {
344
+ limit: Infinity,
345
+ ellipsis: "",
346
+ ellipsisWidth: 0
347
+ };
348
+ const fastStringWidth = (input, options = {}) => {
349
+ return dist_default$1(input, NO_TRUNCATION, options).width;
350
+ };
351
+ var dist_default = fastStringWidth;
352
+
353
+ //#endregion
354
+ //#region node_modules/fast-wrap-ansi/lib/main.js
355
+ const ESC$1 = "\x1B";
356
+ const CSI$1 = "›";
357
+ const END_CODE = 39;
358
+ const ANSI_ESCAPE_BELL = "\x07";
359
+ const ANSI_CSI = "[";
360
+ const ANSI_OSC = "]";
361
+ const ANSI_SGR_TERMINATOR = "m";
362
+ const ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
363
+ const GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
364
+ const getClosingCode = (openingCode) => {
365
+ if (openingCode >= 30 && openingCode <= 37) return 39;
366
+ if (openingCode >= 90 && openingCode <= 97) return 39;
367
+ if (openingCode >= 40 && openingCode <= 47) return 49;
368
+ if (openingCode >= 100 && openingCode <= 107) return 49;
369
+ if (openingCode === 1 || openingCode === 2) return 22;
370
+ if (openingCode === 3) return 23;
371
+ if (openingCode === 4) return 24;
372
+ if (openingCode === 7) return 27;
373
+ if (openingCode === 8) return 28;
374
+ if (openingCode === 9) return 29;
375
+ if (openingCode === 0) return 0;
376
+ };
377
+ const wrapAnsiCode = (code) => `${ESC$1}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
378
+ const wrapAnsiHyperlink = (url) => `${ESC$1}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
379
+ const wrapWord = (rows, word, columns) => {
380
+ const characters = word[Symbol.iterator]();
381
+ let isInsideEscape = false;
382
+ let isInsideLinkEscape = false;
383
+ let lastRow = rows.at(-1);
384
+ let visible = lastRow === void 0 ? 0 : dist_default(lastRow);
385
+ let currentCharacter = characters.next();
386
+ let nextCharacter = characters.next();
387
+ let rawCharacterIndex = 0;
388
+ while (!currentCharacter.done) {
389
+ const character = currentCharacter.value;
390
+ const characterLength = dist_default(character);
391
+ if (visible + characterLength <= columns) rows[rows.length - 1] += character;
392
+ else {
393
+ rows.push(character);
394
+ visible = 0;
395
+ }
396
+ if (character === ESC$1 || character === CSI$1) {
397
+ isInsideEscape = true;
398
+ isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
399
+ }
400
+ if (isInsideEscape) {
401
+ if (isInsideLinkEscape) {
402
+ if (character === ANSI_ESCAPE_BELL) {
403
+ isInsideEscape = false;
404
+ isInsideLinkEscape = false;
405
+ }
406
+ } else if (character === ANSI_SGR_TERMINATOR) isInsideEscape = false;
407
+ } else {
408
+ visible += characterLength;
409
+ if (visible === columns && !nextCharacter.done) {
410
+ rows.push("");
411
+ visible = 0;
412
+ }
413
+ }
414
+ currentCharacter = nextCharacter;
415
+ nextCharacter = characters.next();
416
+ rawCharacterIndex += character.length;
417
+ }
418
+ lastRow = rows.at(-1);
419
+ if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) rows[rows.length - 2] += rows.pop();
420
+ };
421
+ const stringVisibleTrimSpacesRight = (string) => {
422
+ const words = string.split(" ");
423
+ let last = words.length;
424
+ while (last) {
425
+ if (dist_default(words[last - 1])) break;
426
+ last--;
427
+ }
428
+ if (last === words.length) return string;
429
+ return words.slice(0, last).join(" ") + words.slice(last).join("");
430
+ };
431
+ const exec = (string, columns, options = {}) => {
432
+ if (options.trim !== false && string.trim() === "") return "";
433
+ let returnValue = "";
434
+ let escapeCode;
435
+ let escapeUrl;
436
+ const words = string.split(" ");
437
+ let rows = [""];
438
+ let rowLength = 0;
439
+ for (let index = 0; index < words.length; index++) {
440
+ const word = words[index];
441
+ if (options.trim !== false) {
442
+ const row = rows.at(-1) ?? "";
443
+ const trimmed = row.trimStart();
444
+ if (row.length !== trimmed.length) {
445
+ rows[rows.length - 1] = trimmed;
446
+ rowLength = dist_default(trimmed);
447
+ }
448
+ }
449
+ if (index !== 0) {
450
+ if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
451
+ rows.push("");
452
+ rowLength = 0;
453
+ }
454
+ if (rowLength || options.trim === false) {
455
+ rows[rows.length - 1] += " ";
456
+ rowLength++;
457
+ }
458
+ }
459
+ const wordLength = dist_default(word);
460
+ if (options.hard && wordLength > columns) {
461
+ const remainingColumns = columns - rowLength;
462
+ const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
463
+ if (Math.floor((wordLength - 1) / columns) < breaksStartingThisLine) rows.push("");
464
+ wrapWord(rows, word, columns);
465
+ rowLength = dist_default(rows.at(-1) ?? "");
466
+ continue;
467
+ }
468
+ if (rowLength + wordLength > columns && rowLength && wordLength) {
469
+ if (options.wordWrap === false && rowLength < columns) {
470
+ wrapWord(rows, word, columns);
471
+ rowLength = dist_default(rows.at(-1) ?? "");
472
+ continue;
473
+ }
474
+ rows.push("");
475
+ rowLength = 0;
476
+ }
477
+ if (rowLength + wordLength > columns && options.wordWrap === false) {
478
+ wrapWord(rows, word, columns);
479
+ rowLength = dist_default(rows.at(-1) ?? "");
480
+ continue;
481
+ }
482
+ rows[rows.length - 1] += word;
483
+ rowLength += wordLength;
484
+ }
485
+ if (options.trim !== false) rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
486
+ const preString = rows.join("\n");
487
+ let inSurrogate = false;
488
+ for (let i$1 = 0; i$1 < preString.length; i$1++) {
489
+ const character = preString[i$1];
490
+ returnValue += character;
491
+ if (!inSurrogate) {
492
+ inSurrogate = character >= "\ud800" && character <= "\udbff";
493
+ if (inSurrogate) continue;
494
+ } else inSurrogate = false;
495
+ if (character === ESC$1 || character === CSI$1) {
496
+ GROUP_REGEX.lastIndex = i$1 + 1;
497
+ const groups = GROUP_REGEX.exec(preString)?.groups;
498
+ if (groups?.code !== void 0) {
499
+ const code = Number.parseFloat(groups.code);
500
+ escapeCode = code === END_CODE ? void 0 : code;
501
+ } else if (groups?.uri !== void 0) escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
502
+ }
503
+ if (preString[i$1 + 1] === "\n") {
504
+ if (escapeUrl) returnValue += wrapAnsiHyperlink("");
505
+ const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
506
+ if (escapeCode && closingCode) returnValue += wrapAnsiCode(closingCode);
507
+ } else if (character === "\n") {
508
+ if (escapeCode && getClosingCode(escapeCode)) returnValue += wrapAnsiCode(escapeCode);
509
+ if (escapeUrl) returnValue += wrapAnsiHyperlink(escapeUrl);
510
+ }
511
+ }
512
+ return returnValue;
513
+ };
514
+ const CRLF_OR_LF = /\r?\n/;
515
+ function wrapAnsi(string, columns, options) {
516
+ return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
517
+ }
518
+
519
+ //#endregion
520
+ //#region node_modules/sisteransi/src/index.js
521
+ var require_src = /* @__PURE__ */ __commonJS({ "node_modules/sisteransi/src/index.js": ((exports, module) => {
522
+ const ESC = "\x1B";
523
+ const CSI = `${ESC}[`;
524
+ const beep = "\x07";
525
+ const cursor$2 = {
526
+ to(x, y) {
527
+ if (!y) return `${CSI}${x + 1}G`;
528
+ return `${CSI}${y + 1};${x + 1}H`;
529
+ },
530
+ move(x, y) {
531
+ let ret = "";
532
+ if (x < 0) ret += `${CSI}${-x}D`;
533
+ else if (x > 0) ret += `${CSI}${x}C`;
534
+ if (y < 0) ret += `${CSI}${-y}A`;
535
+ else if (y > 0) ret += `${CSI}${y}B`;
536
+ return ret;
537
+ },
538
+ up: (count = 1) => `${CSI}${count}A`,
539
+ down: (count = 1) => `${CSI}${count}B`,
540
+ forward: (count = 1) => `${CSI}${count}C`,
541
+ backward: (count = 1) => `${CSI}${count}D`,
542
+ nextLine: (count = 1) => `${CSI}E`.repeat(count),
543
+ prevLine: (count = 1) => `${CSI}F`.repeat(count),
544
+ left: `${CSI}G`,
545
+ hide: `${CSI}?25l`,
546
+ show: `${CSI}?25h`,
547
+ save: `${ESC}7`,
548
+ restore: `${ESC}8`
549
+ };
550
+ const scroll = {
551
+ up: (count = 1) => `${CSI}S`.repeat(count),
552
+ down: (count = 1) => `${CSI}T`.repeat(count)
553
+ };
554
+ const erase$2 = {
555
+ screen: `${CSI}2J`,
556
+ up: (count = 1) => `${CSI}1J`.repeat(count),
557
+ down: (count = 1) => `${CSI}J`.repeat(count),
558
+ line: `${CSI}2K`,
559
+ lineEnd: `${CSI}K`,
560
+ lineStart: `${CSI}1K`,
561
+ lines(count) {
562
+ let clear = "";
563
+ for (let i$1 = 0; i$1 < count; i$1++) clear += this.line + (i$1 < count - 1 ? cursor$2.up() : "");
564
+ if (count) clear += cursor$2.left;
565
+ return clear;
566
+ }
567
+ };
568
+ module.exports = {
569
+ cursor: cursor$2,
570
+ scroll,
571
+ erase: erase$2,
572
+ beep
573
+ };
574
+ }) });
575
+
576
+ //#endregion
577
+ //#region node_modules/@clack/core/dist/index.mjs
578
+ var import_src$1 = /* @__PURE__ */ __toESM(require_src(), 1);
579
+ function findCursor(s, o, l) {
580
+ if (!l.some((r$1) => !r$1.disabled)) return s;
581
+ const t = s + o, n$2 = Math.max(l.length - 1, 0), e = t < 0 ? n$2 : t > n$2 ? 0 : t;
582
+ return l[e]?.disabled ? findCursor(e, o < 0 ? -1 : 1, l) : e;
583
+ }
584
+ const settings = {
585
+ actions: new Set([
586
+ "up",
587
+ "down",
588
+ "left",
589
+ "right",
590
+ "space",
591
+ "enter",
592
+ "cancel"
593
+ ]),
594
+ aliases: /* @__PURE__ */ new Map([
595
+ ["k", "up"],
596
+ ["j", "down"],
597
+ ["h", "left"],
598
+ ["l", "right"],
599
+ ["", "cancel"],
600
+ ["escape", "cancel"]
601
+ ]),
602
+ messages: {
603
+ cancel: "Canceled",
604
+ error: "Something went wrong"
605
+ },
606
+ withGuide: true,
607
+ date: {
608
+ monthNames: [...[
609
+ "January",
610
+ "February",
611
+ "March",
612
+ "April",
613
+ "May",
614
+ "June",
615
+ "July",
616
+ "August",
617
+ "September",
618
+ "October",
619
+ "November",
620
+ "December"
621
+ ]],
622
+ messages: {
623
+ required: "Please enter a valid date",
624
+ invalidMonth: "There are only 12 months in a year",
625
+ invalidDay: (n$2, e) => `There are only ${n$2} days in ${e}`,
626
+ afterMin: (n$2) => `Date must be on or after ${n$2.toISOString().slice(0, 10)}`,
627
+ beforeMax: (n$2) => `Date must be on or before ${n$2.toISOString().slice(0, 10)}`
628
+ }
629
+ }
630
+ };
631
+ function isActionKey(n$2, e) {
632
+ if (typeof n$2 == "string") return settings.aliases.get(n$2) === e;
633
+ for (const s of n$2) if (s !== void 0 && isActionKey(s, e)) return true;
634
+ return false;
635
+ }
636
+ function diffLines(i$1, s) {
637
+ if (i$1 === s) return;
638
+ const e = i$1.split(`
639
+ `), t = s.split(`
640
+ `), r$1 = Math.max(e.length, t.length), f = [];
641
+ for (let n$2 = 0; n$2 < r$1; n$2++) e[n$2] !== t[n$2] && f.push(n$2);
642
+ return {
643
+ lines: f,
644
+ numLinesBefore: e.length,
645
+ numLinesAfter: t.length,
646
+ numLines: r$1
647
+ };
648
+ }
649
+ const R = globalThis.process.platform.startsWith("win");
650
+ const CANCEL_SYMBOL = Symbol("clack:cancel");
651
+ function isCancel(e) {
652
+ return e === CANCEL_SYMBOL;
653
+ }
654
+ function setRawMode(e, r$1) {
655
+ const o = e;
656
+ o.isTTY && o.setRawMode(r$1);
657
+ }
658
+ const getColumns = (e) => "columns" in e && typeof e.columns == "number" ? e.columns : 80, getRows = (e) => "rows" in e && typeof e.rows == "number" ? e.rows : 20;
659
+ function wrapTextWithPrefix(e, r$1, o, t = o, s = o, n$2) {
660
+ return wrapAnsi(r$1, getColumns(e ?? stdout) - o.length, {
661
+ hard: true,
662
+ trim: false
663
+ }).split(`
664
+ `).map((c, i$1, m$1) => {
665
+ const d = n$2 ? n$2(c, i$1) : c;
666
+ return i$1 === 0 ? `${t}${d}` : i$1 === m$1.length - 1 ? `${s}${d}` : `${o}${d}`;
667
+ }).join(`
668
+ `);
669
+ }
670
+ function runValidation(e, n$2) {
671
+ if ("~standard" in e) {
672
+ const a$1 = e["~standard"].validate(n$2);
673
+ if (a$1 instanceof Promise) throw new TypeError("Schema validation must be synchronous. Update `validate()` and remove any asynchronous logic.");
674
+ return a$1.issues?.at(0)?.message;
675
+ }
676
+ return e(n$2);
677
+ }
678
+ var V = class {
679
+ input;
680
+ output;
681
+ _abortSignal;
682
+ rl;
683
+ opts;
684
+ _render;
685
+ _track = false;
686
+ _prevFrame = "";
687
+ _subscribers = /* @__PURE__ */ new Map();
688
+ _cursor = 0;
689
+ state = "initial";
690
+ error = "";
691
+ value;
692
+ userInput = "";
693
+ constructor(t, e = true) {
694
+ const { input: i$1 = stdin, output: n$2 = stdout, render: s, signal: r$1,...o } = t;
695
+ this.opts = o, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = s.bind(this), this._track = e, this._abortSignal = r$1, this.input = i$1, this.output = n$2;
696
+ }
697
+ /**
698
+ * Unsubscribe all listeners
699
+ */
700
+ unsubscribe() {
701
+ this._subscribers.clear();
702
+ }
703
+ /**
704
+ * Set a subscriber with opts
705
+ * @param event - The event name
706
+ */
707
+ setSubscriber(t, e) {
708
+ const i$1 = this._subscribers.get(t) ?? [];
709
+ i$1.push(e), this._subscribers.set(t, i$1);
710
+ }
711
+ /**
712
+ * Subscribe to an event
713
+ * @param event - The event name
714
+ * @param cb - The callback
715
+ */
716
+ on(t, e) {
717
+ this.setSubscriber(t, { cb: e });
718
+ }
719
+ /**
720
+ * Subscribe to an event once
721
+ * @param event - The event name
722
+ * @param cb - The callback
723
+ */
724
+ once(t, e) {
725
+ this.setSubscriber(t, {
726
+ cb: e,
727
+ once: true
728
+ });
729
+ }
730
+ /**
731
+ * Emit an event with data
732
+ * @param event - The event name
733
+ * @param data - The data to pass to the callback
734
+ */
735
+ emit(t, ...e) {
736
+ const i$1 = this._subscribers.get(t) ?? [], n$2 = [];
737
+ for (const s of i$1) s.cb(...e), s.once && n$2.push(() => i$1.splice(i$1.indexOf(s), 1));
738
+ for (const s of n$2) s();
739
+ }
740
+ prompt() {
741
+ return new Promise((t) => {
742
+ if (this._abortSignal) {
743
+ if (this._abortSignal.aborted) return this.state = "cancel", this.close(), t(CANCEL_SYMBOL);
744
+ this._abortSignal.addEventListener("abort", () => {
745
+ this.state = "cancel", this.close();
746
+ }, { once: true });
747
+ }
748
+ this.rl = l__default.createInterface({
749
+ input: this.input,
750
+ tabSize: 2,
751
+ prompt: "",
752
+ escapeCodeTimeout: 50,
753
+ terminal: true
754
+ }), this.rl.prompt(), this.opts.initialUserInput !== void 0 && this._setUserInput(this.opts.initialUserInput, true), this.input.on("keypress", this.onKeypress), setRawMode(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
755
+ this.output.write(import_src$1.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t(this.value);
756
+ }), this.once("cancel", () => {
757
+ this.output.write(import_src$1.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t(CANCEL_SYMBOL);
758
+ });
759
+ });
760
+ }
761
+ _isActionKey(t, e) {
762
+ return t === " ";
763
+ }
764
+ _shouldSubmit(t, e) {
765
+ return true;
766
+ }
767
+ _setValue(t) {
768
+ this.value = t, this.emit("value", this.value);
769
+ }
770
+ _setUserInput(t, e) {
771
+ this.userInput = t ?? "", this.emit("userInput", this.userInput), e && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
772
+ }
773
+ _clearUserInput() {
774
+ this.rl?.write(null, {
775
+ ctrl: true,
776
+ name: "u"
777
+ }), this._setUserInput("");
778
+ }
779
+ onKeypress(t, e) {
780
+ if (this._track && e.name !== "return" && (e.name && this._isActionKey(t, e) && this.rl?.write(null, {
781
+ ctrl: true,
782
+ name: "h"
783
+ }), this._cursor = this.rl?.cursor ?? 0, this._setUserInput(this.rl?.line)), this.state === "error" && (this.state = "active"), e?.name && (!this._track && settings.aliases.has(e.name) && this.emit("cursor", settings.aliases.get(e.name)), settings.actions.has(e.name) && this.emit("cursor", e.name)), t && (t.toLowerCase() === "y" || t.toLowerCase() === "n") && this.emit("confirm", t.toLowerCase() === "y"), this.emit("key", t, e), e?.name === "return" && this._shouldSubmit(t, e)) {
784
+ if (this.opts.validate) {
785
+ const i$1 = runValidation(this.opts.validate, this.value);
786
+ i$1 && (this.error = i$1 instanceof Error ? i$1.message : i$1, this.state = "error", this.rl?.write(this.userInput));
787
+ }
788
+ this.state !== "error" && (this.state = "submit");
789
+ }
790
+ isActionKey([
791
+ t,
792
+ e?.name,
793
+ e?.sequence
794
+ ], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
795
+ }
796
+ close() {
797
+ this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
798
+ `), setRawMode(this.input, false), this.rl?.close(), this.rl = void 0, this.emit(`${this.state}`, this.value), this.unsubscribe();
799
+ }
800
+ restoreCursor() {
801
+ const t = wrapAnsi(this._prevFrame, process.stdout.columns, {
802
+ hard: true,
803
+ trim: false
804
+ }).split(`
805
+ `).length - 1;
806
+ this.output.write(import_src$1.cursor.move(-999, t * -1));
807
+ }
808
+ render() {
809
+ const t = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
810
+ hard: true,
811
+ trim: false
812
+ });
813
+ if (t !== this._prevFrame) {
814
+ if (this.state === "initial") this.output.write(import_src$1.cursor.hide);
815
+ else {
816
+ const e = diffLines(this._prevFrame, t), i$1 = getRows(this.output);
817
+ if (this.restoreCursor(), e) {
818
+ const n$2 = Math.max(0, e.numLinesAfter - i$1), s = Math.max(0, e.numLinesBefore - i$1);
819
+ let r$1 = e.lines.find((o) => o >= n$2);
820
+ if (r$1 === void 0) {
821
+ this._prevFrame = t;
822
+ return;
823
+ }
824
+ if (e.lines.length === 1) {
825
+ this.output.write(import_src$1.cursor.move(0, r$1 - s)), this.output.write(import_src$1.erase.lines(1));
826
+ const o = t.split(`
827
+ `);
828
+ this.output.write(o[r$1]), this._prevFrame = t, this.output.write(import_src$1.cursor.move(0, o.length - r$1 - 1));
829
+ return;
830
+ } else if (e.lines.length > 1) {
831
+ if (n$2 < s) r$1 = n$2;
832
+ else {
833
+ const h$1 = r$1 - s;
834
+ h$1 > 0 && this.output.write(import_src$1.cursor.move(0, h$1));
835
+ }
836
+ this.output.write(import_src$1.erase.down());
837
+ const f = t.split(`
838
+ `).slice(r$1);
839
+ this.output.write(f.join(`
840
+ `)), this._prevFrame = t;
841
+ return;
842
+ }
843
+ }
844
+ this.output.write(import_src$1.erase.down());
845
+ }
846
+ this.output.write(t), this.state === "initial" && (this.state = "active"), this._prevFrame = t;
847
+ }
848
+ }
849
+ };
850
+ var a = class extends V {
851
+ options;
852
+ cursor = 0;
853
+ get _value() {
854
+ return this.options[this.cursor]?.value;
855
+ }
856
+ get _enabledOptions() {
857
+ return this.options.filter((e) => e.disabled !== true);
858
+ }
859
+ toggleAll() {
860
+ const e = this._enabledOptions;
861
+ this.value = this.value !== void 0 && this.value.length === e.length ? [] : e.map((t) => t.value);
862
+ }
863
+ toggleInvert() {
864
+ const e = this.value;
865
+ if (!e) return;
866
+ this.value = this._enabledOptions.filter((t) => !e.includes(t.value)).map((t) => t.value);
867
+ }
868
+ toggleValue() {
869
+ this.value === void 0 && (this.value = []);
870
+ this.value = this.value.includes(this._value) ? this.value.filter((i$1) => i$1 !== this._value) : [...this.value, this._value];
871
+ }
872
+ constructor(e) {
873
+ super(e, false), this.options = e.options, this.value = [...e.initialValues ?? []];
874
+ const i$1 = Math.max(this.options.findIndex(({ value: t }) => t === e.cursorAt), 0);
875
+ this.cursor = this.options[i$1]?.disabled ? findCursor(i$1, 1, this.options) : i$1, this.on("key", (t, l) => {
876
+ l.name === "a" && this.toggleAll(), l.name === "i" && this.toggleInvert();
877
+ }), this.on("cursor", (t) => {
878
+ switch (t) {
879
+ case "left":
880
+ case "up":
881
+ this.cursor = findCursor(this.cursor, -1, this.options);
882
+ break;
883
+ case "down":
884
+ case "right":
885
+ this.cursor = findCursor(this.cursor, 1, this.options);
886
+ break;
887
+ case "space":
888
+ this.toggleValue();
889
+ break;
890
+ }
891
+ });
892
+ }
893
+ };
894
+
895
+ //#endregion
896
+ //#region node_modules/@clack/prompts/dist/index.mjs
897
+ var import_src = /* @__PURE__ */ __toESM(require_src(), 1);
898
+ function isUnicodeSupported() {
899
+ if (process$1.platform !== "win32") return process$1.env.TERM !== "linux";
900
+ return Boolean(process$1.env.CI) || Boolean(process$1.env.WT_SESSION) || Boolean(process$1.env.TERMINUS_SUBLIME) || process$1.env.ConEmuTask === "{cmd::Cmder}" || process$1.env.TERM_PROGRAM === "Terminus-Sublime" || process$1.env.TERM_PROGRAM === "vscode" || process$1.env.TERM === "xterm-256color" || process$1.env.TERM === "alacritty" || process$1.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
901
+ }
902
+ const unicode = isUnicodeSupported(), isCI = () => process.env.CI === "true", isTTY = (o) => o.isTTY === true, unicodeOr = (o, e) => unicode ? o : e, S_STEP_ACTIVE = unicodeOr("◆", "*"), S_STEP_CANCEL = unicodeOr("■", "x"), S_STEP_ERROR = unicodeOr("▲", "x"), S_STEP_SUBMIT = unicodeOr("◇", "o"), S_BAR_START = unicodeOr("┌", "T"), S_BAR = unicodeOr("│", "|"), S_BAR_END = unicodeOr("└", "—"), S_BAR_START_RIGHT = unicodeOr("┐", "T"), S_BAR_END_RIGHT = unicodeOr("┘", "—"), S_RADIO_ACTIVE = unicodeOr("●", ">"), S_RADIO_INACTIVE = unicodeOr("○", " "), S_CHECKBOX_ACTIVE = unicodeOr("◻", "[•]"), S_CHECKBOX_SELECTED = unicodeOr("◼", "[+]"), S_CHECKBOX_INACTIVE = unicodeOr("◻", "[ ]"), S_PASSWORD_MASK = unicodeOr("▪", "•"), S_BAR_H = unicodeOr("─", "-"), S_CORNER_TOP_RIGHT = unicodeOr("╮", "+"), S_CONNECT_LEFT = unicodeOr("├", "+"), S_CORNER_BOTTOM_RIGHT = unicodeOr("╯", "+"), S_CORNER_BOTTOM_LEFT = unicodeOr("╰", "+"), S_CORNER_TOP_LEFT = unicodeOr("╭", "+"), S_INFO = unicodeOr("●", "•"), S_SUCCESS = unicodeOr("◆", "*"), S_WARN = unicodeOr("▲", "!"), S_ERROR = unicodeOr("■", "x"), symbol = (o) => {
903
+ switch (o) {
904
+ case "initial":
905
+ case "active": return styleText("cyan", S_STEP_ACTIVE);
906
+ case "cancel": return styleText("red", S_STEP_CANCEL);
907
+ case "error": return styleText("yellow", S_STEP_ERROR);
908
+ case "submit": return styleText("green", S_STEP_SUBMIT);
909
+ }
910
+ }, symbolBar = (o) => {
911
+ switch (o) {
912
+ case "initial":
913
+ case "active": return styleText("cyan", S_BAR);
914
+ case "cancel": return styleText("red", S_BAR);
915
+ case "error": return styleText("yellow", S_BAR);
916
+ case "submit": return styleText("green", S_BAR);
917
+ }
918
+ };
919
+ function formatInstructionFooter(o, e) {
920
+ const r$1 = [`${e ? `${styleText("cyan", S_BAR)} ` : ""}${o.join(" • ")}`];
921
+ return e && r$1.push(styleText("cyan", S_BAR_END)), r$1;
922
+ }
923
+ const I = (l, e, w, p$1, b, C = false) => {
924
+ let r$1 = e, O = 0;
925
+ if (C) for (let i$1 = p$1 - 1; i$1 >= w; i$1--) {
926
+ const m$1 = l[i$1];
927
+ if (m$1 && (r$1 -= m$1.length), O++, r$1 <= b) break;
928
+ }
929
+ else for (let i$1 = w; i$1 < p$1; i$1++) {
930
+ const m$1 = l[i$1];
931
+ if (m$1 && (r$1 -= m$1.length), O++, r$1 <= b) break;
932
+ }
933
+ return {
934
+ lineCount: r$1,
935
+ removals: O
936
+ };
937
+ };
938
+ const limitOptions = ({ cursor: l, options: e, style: w, output: p$1 = process.stdout, maxItems: b = Number.POSITIVE_INFINITY, columnPadding: C = 0, rowPadding: r$1 = 4 }) => {
939
+ const i$1 = getColumns(p$1) - C, m$1 = getRows(p$1), M = styleText("dim", "..."), v = Math.max(m$1 - r$1, 0), a$1 = Math.max(Math.min(b, v), 5);
940
+ let f = 0;
941
+ l >= a$1 - 3 && (f = Math.max(Math.min(l - a$1 + 3, e.length - a$1), 0));
942
+ let d = a$1 < e.length && f > 0, c = a$1 < e.length && f + a$1 < e.length;
943
+ const W = Math.min(f + a$1, e.length), s = [];
944
+ let g = 0;
945
+ d && g++, c && g++;
946
+ const T = f + (d ? 1 : 0), y = W - (c ? 1 : 0);
947
+ for (let t = T; t < y; t++) {
948
+ const n$2 = e[t], h$1 = wrapAnsi(n$2 ? w(n$2, t === l) : "", i$1, {
949
+ hard: true,
950
+ trim: false
951
+ }).split(`
952
+ `);
953
+ s.push(h$1), g += h$1.length;
954
+ }
955
+ if (g > v) {
956
+ let t = 0, n$2 = 0, o = g;
957
+ const h$1 = l - T;
958
+ let u$4 = v;
959
+ const L = () => I(s, o, 0, h$1, u$4), E = () => I(s, o, h$1 + 1, s.length, u$4, true);
960
+ d ? ({lineCount: o, removals: t} = L(), o > u$4 && (c || (u$4 -= 1), {lineCount: o, removals: n$2} = E())) : (c || (u$4 -= 1), {lineCount: o, removals: n$2} = E(), o > u$4 && (u$4 -= 1, {lineCount: o, removals: t} = L())), t > 0 && (d = true, s.splice(0, t)), n$2 > 0 && (c = true, s.splice(s.length - n$2, n$2));
961
+ }
962
+ const x = [];
963
+ d && x.push(M);
964
+ for (const t of s) for (const n$2 of t) x.push(n$2);
965
+ return c && x.push(M), x;
966
+ };
967
+ const MULTISELECT_INSTRUCTIONS = [
968
+ `${styleText("dim", "↑/↓")} to navigate`,
969
+ `${styleText("dim", "Space:")} select`,
970
+ `${styleText("dim", "Enter:")} confirm`
971
+ ];
972
+ const m = (i$1, u$4) => i$1.split(`
973
+ `).map((d) => u$4(d)).join(`
974
+ `);
975
+ const multiselect = (i$1) => {
976
+ const u$4 = (t, a$1) => {
977
+ const r$1 = t.label ?? String(t.value);
978
+ return a$1 === "disabled" ? `${styleText("gray", S_CHECKBOX_INACTIVE)} ${m(r$1, (o) => styleText(["strikethrough", "gray"], o))}${t.hint ? ` ${styleText("dim", `(${t.hint ?? "disabled"})`)}` : ""}` : a$1 === "active" ? `${styleText("cyan", S_CHECKBOX_ACTIVE)} ${r$1}${t.hint ? ` ${styleText("dim", `(${t.hint})`)}` : ""}` : a$1 === "selected" ? `${styleText("green", S_CHECKBOX_SELECTED)} ${m(r$1, (o) => styleText("dim", o))}${t.hint ? ` ${styleText("dim", `(${t.hint})`)}` : ""}` : a$1 === "cancelled" ? `${m(r$1, (o) => styleText(["strikethrough", "dim"], o))}` : a$1 === "active-selected" ? `${styleText("green", S_CHECKBOX_SELECTED)} ${r$1}${t.hint ? ` ${styleText("dim", `(${t.hint})`)}` : ""}` : a$1 === "submitted" ? `${m(r$1, (o) => styleText("dim", o))}` : `${styleText("dim", S_CHECKBOX_INACTIVE)} ${m(r$1, (o) => styleText("dim", o))}`;
979
+ }, d = i$1.required ?? true, v = i$1.showInstructions ?? true;
980
+ return new a({
981
+ options: i$1.options,
982
+ signal: i$1.signal,
983
+ input: i$1.input,
984
+ output: i$1.output,
985
+ initialValues: i$1.initialValues,
986
+ required: d,
987
+ cursorAt: i$1.cursorAt,
988
+ validate(t) {
989
+ if (d && (t === void 0 || t.length === 0)) return `Please select at least one option.
990
+ ${styleText("reset", styleText("dim", `Press ${styleText([
991
+ "gray",
992
+ "bgWhite",
993
+ "inverse"
994
+ ], " space ")} to select, ${styleText("gray", styleText("bgWhite", styleText("inverse", " enter ")))} to submit`))}`;
995
+ },
996
+ render() {
997
+ const t = i$1.withGuide ?? settings.withGuide, a$1 = wrapTextWithPrefix(i$1.output, i$1.message, t ? `${symbolBar(this.state)} ` : "", `${symbol(this.state)} `), r$1 = `${t ? `${styleText("gray", S_BAR)}
998
+ ` : ""}${a$1}
999
+ `, o = this.value ?? [], p$1 = (n$2, l) => {
1000
+ if (n$2.disabled) return u$4(n$2, "disabled");
1001
+ const s = o.includes(n$2.value);
1002
+ return l && s ? u$4(n$2, "active-selected") : s ? u$4(n$2, "selected") : u$4(n$2, l ? "active" : "inactive");
1003
+ };
1004
+ switch (this.state) {
1005
+ case "submit": {
1006
+ const n$2 = this.options.filter(({ value: s }) => o.includes(s)).map((s) => u$4(s, "submitted")).join(styleText("dim", ", ")) || styleText("dim", "none");
1007
+ return `${r$1}${wrapTextWithPrefix(i$1.output, n$2, t ? `${styleText("gray", S_BAR)} ` : "")}`;
1008
+ }
1009
+ case "cancel": {
1010
+ const n$2 = this.options.filter(({ value: s }) => o.includes(s)).map((s) => u$4(s, "cancelled")).join(styleText("dim", ", "));
1011
+ if (n$2.trim() === "") return `${r$1}${styleText("gray", S_BAR)}`;
1012
+ return `${r$1}${wrapTextWithPrefix(i$1.output, n$2, t ? `${styleText("gray", S_BAR)} ` : "")}${t ? `
1013
+ ${styleText("gray", S_BAR)}` : ""}`;
1014
+ }
1015
+ case "error": {
1016
+ const n$2 = t ? `${styleText("yellow", S_BAR)} ` : "", l = this.error.split(`
1017
+ `).map(($, C) => C === 0 ? `${t ? `${styleText("yellow", S_BAR_END)} ` : ""}${styleText("yellow", $)}` : ` ${$}`).join(`
1018
+ `), s = r$1.split(`
1019
+ `).length, h$1 = l.split(`
1020
+ `).length + 1;
1021
+ return `${r$1}${n$2}${limitOptions({
1022
+ output: i$1.output,
1023
+ options: this.options,
1024
+ cursor: this.cursor,
1025
+ maxItems: i$1.maxItems,
1026
+ columnPadding: n$2.length,
1027
+ rowPadding: s + h$1,
1028
+ style: p$1
1029
+ }).join(`
1030
+ ${n$2}`)}
1031
+ ${l}
1032
+ `;
1033
+ }
1034
+ default: {
1035
+ const n$2 = t ? `${styleText("cyan", S_BAR)} ` : "", l = r$1.split(`
1036
+ `).length, s = v ? formatInstructionFooter(MULTISELECT_INSTRUCTIONS, t) : t ? [styleText("cyan", S_BAR_END)] : [], h$1 = s.join(`
1037
+ `), $ = s.length + 1;
1038
+ return `${r$1}${n$2}${limitOptions({
1039
+ output: i$1.output,
1040
+ options: this.options,
1041
+ cursor: this.cursor,
1042
+ maxItems: i$1.maxItems,
1043
+ columnPadding: n$2.length,
1044
+ rowPadding: l + $,
1045
+ style: p$1
1046
+ }).join(`
1047
+ ${n$2}`)}
1048
+ ${h$1}
1049
+ `;
1050
+ }
1051
+ }
1052
+ }
1053
+ }).prompt();
1054
+ };
1055
+ const cancel = (o = "", t) => {
1056
+ const i$1 = t?.output ?? process.stdout, e = t?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR_END)} ` : "";
1057
+ i$1.write(`${e}${styleText("red", o)}
1058
+
1059
+ `);
1060
+ }, intro = (o = "", t) => {
1061
+ const i$1 = t?.output ?? process.stdout, e = t?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR_START)} ` : "";
1062
+ i$1.write(`${e}${o}
1063
+ `);
1064
+ }, outro = (o = "", t) => {
1065
+ const i$1 = t?.output ?? process.stdout, e = t?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR)}
1066
+ ${styleText("gray", S_BAR_END)} ` : "";
1067
+ i$1.write(`${e}${o}
1068
+
1069
+ `);
1070
+ };
1071
+ const u$3 = {
1072
+ light: unicodeOr("─", "-"),
1073
+ heavy: unicodeOr("━", "="),
1074
+ block: unicodeOr("█", "#")
1075
+ };
1076
+ const SELECT_INSTRUCTIONS = [`${styleText("dim", "↑/↓")} to navigate`, `${styleText("dim", "Enter:")} confirm`];
1077
+ const i = `${styleText("gray", S_BAR)} `;
1078
+
1079
+ //#endregion
1080
+ //#region src/util/prompt.ts
1081
+ /** Space to toggle, `a` for all, enter to confirm. Cancelling selects nothing. */
1082
+ async function multiSelect(message, choices) {
1083
+ if (!choices.length) return [];
1084
+ const picked = await multiselect({
1085
+ message,
1086
+ options: choices.map((c) => ({
1087
+ value: c.value,
1088
+ label: c.label,
1089
+ hint: c.hint
1090
+ })),
1091
+ initialValues: choices.map((c) => c.value),
1092
+ required: false
1093
+ });
1094
+ if (isCancel(picked)) {
1095
+ cancel("cancelled");
1096
+ return [];
1097
+ }
1098
+ return picked;
1099
+ }
1100
+ function isInteractive() {
1101
+ return Boolean(process.stdin.isTTY && process.stdout.isTTY);
1102
+ }
1103
+ /**
1104
+ * Ask only when the user has not already decided and someone is there to answer. A prompt in
1105
+ * a piped or scripted run would hang forever, so this is the one gate that must not regress.
1106
+ */
1107
+ function shouldAsk(opts) {
1108
+ return opts.requested === 0 && !opts.all && opts.interactive;
1109
+ }
1110
+
1111
+ //#endregion
1112
+ //#region src/util/fs.ts
1113
+ async function exists(p$1) {
1114
+ try {
1115
+ await lstat(p$1);
1116
+ return true;
1117
+ } catch {
1118
+ return false;
1119
+ }
1120
+ }
1121
+ async function ensureDir(path) {
1122
+ await mkdir(path, { recursive: true });
1123
+ }
1124
+ async function backup(path, archiveDir) {
1125
+ if (!await exists(path)) return null;
1126
+ const dest = join(archiveDir, basename(path));
1127
+ await ensureDir(archiveDir);
1128
+ await copyFile(path, dest);
1129
+ return dest;
1130
+ }
1131
+ function stable(value) {
1132
+ if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
1133
+ if (Array.isArray(value)) return `[${value.map(stable).join(",")}]`;
1134
+ return `{${Object.entries(value).sort(([a$1], [b]) => a$1 < b ? -1 : a$1 > b ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${stable(v)}`).join(",")}}`;
1135
+ }
1136
+ async function writeJson(path, value) {
1137
+ await ensureDir(dirname(path));
1138
+ await writeFile(path, `${JSON.stringify(value, null, 2)}\n`);
1139
+ }
1140
+
1141
+ //#endregion
1142
+ //#region src/commands/setup/agents/extensions.ts
1143
+ /** The delivery an extension uses on one agent, or null when it deliberately reaches none. */
1144
+ function deliveryFor(extension, agent) {
1145
+ const declared = extension.deliver[agent] ?? extension.deliver.all;
1146
+ if (!declared) throw new Error(`extension "${extension.name}" declares no delivery for ${agent}`);
1147
+ return typeof declared === "string" ? null : declared;
1148
+ }
1149
+ function skillDeliveries(config$1, agent) {
1150
+ const out = [];
1151
+ for (const extension of config$1.extensions) {
1152
+ const delivery = deliveryFor(extension, agent);
1153
+ if (delivery?.via === "skills") out.push(delivery);
1154
+ }
1155
+ return out;
1156
+ }
1157
+ function claudePluginDeliveries(config$1) {
1158
+ const out = [];
1159
+ for (const extension of config$1.extensions) {
1160
+ const delivery = deliveryFor(extension, "claude-code");
1161
+ if (delivery?.via === "claude-plugin") out.push(delivery);
1162
+ }
1163
+ return out;
1164
+ }
1165
+ function opencodePluginPackages(config$1) {
1166
+ const out = [];
1167
+ for (const extension of config$1.extensions) {
1168
+ const delivery = deliveryFor(extension, "opencode");
1169
+ if (delivery?.via === "opencode-plugin") out.push(delivery.package);
1170
+ }
1171
+ return out;
1172
+ }
1173
+ /** MCP servers this agent should run, keyed by extension name. */
1174
+ function mcpServersFor(config$1, agent) {
1175
+ const out = {};
1176
+ for (const extension of config$1.extensions) {
1177
+ const delivery = deliveryFor(extension, agent);
1178
+ if (delivery?.via === "mcp") out[extension.name] = delivery.server;
1179
+ }
1180
+ return out;
1181
+ }
1182
+ /**
1183
+ * Every extension must resolve on every configured agent, and every `claude-plugin` delivery
1184
+ * must name a declared marketplace. Runs before any emitter so a gap fails the whole run
1185
+ * rather than silently under-installing one agent.
1186
+ */
1187
+ function validateExtensions(config$1) {
1188
+ const problems = [];
1189
+ for (const extension of config$1.extensions) {
1190
+ for (const agent of config$1.agents) if (!(extension.deliver[agent] ?? extension.deliver.all)) problems.push(`${extension.name}: no delivery for ${agent} — add one, or "unsupported"/"skip"`);
1191
+ for (const [key, delivery] of Object.entries(extension.deliver)) {
1192
+ if (key !== "all" && !config$1.agents.includes(key)) problems.push(`${extension.name}: delivery for "${key}", which is not in config.agents`);
1193
+ if (typeof delivery === "object" && delivery.via === "claude-plugin") {
1194
+ if (!config$1.marketplaces[delivery.marketplace]) problems.push(`${extension.name}: unknown marketplace "${delivery.marketplace}"`);
1195
+ }
1196
+ }
1197
+ }
1198
+ if (problems.length) throw new Error(`config.extensions is incomplete:\n - ${problems.join("\n - ")}`);
1199
+ }
1200
+ /** One line per extension showing how it reaches each agent — "does X cover opencode?". */
1201
+ function logCoverage(config$1) {
1202
+ log.section("Extensions");
1203
+ const rows = config$1.extensions.map((extension) => ({
1204
+ name: extension.name,
1205
+ cells: config$1.agents.map((agent) => {
1206
+ const declared = extension.deliver[agent] ?? extension.deliver.all;
1207
+ return `${agent} → ${typeof declared === "string" ? declared : declared.via}`;
1208
+ })
1209
+ }));
1210
+ const nameWidth = Math.max(...rows.map((r$1) => r$1.name.length));
1211
+ const cellWidths = config$1.agents.map((_, i$1) => Math.max(...rows.map((r$1) => r$1.cells[i$1].length)));
1212
+ for (const { name: name$1, cells } of rows) {
1213
+ const line = cells.map((c, i$1) => c.padEnd(cellWidths[i$1])).join(" ");
1214
+ log.info(`${name$1.padEnd(nameWidth)} ${line.trimEnd()}`);
1215
+ }
1216
+ }
1217
+
1218
+ //#endregion
1219
+ //#region src/commands/setup/agents/installs.ts
1220
+ const SKILL_LOCK = ".agents/.skill-lock.json";
1221
+ const MARKETPLACE_REGISTRY = ".claude/plugins/known_marketplaces.json";
1222
+ /**
1223
+ * `claude plugin` installs, preceded by the marketplaces they come from. Each marketplace
1224
+ * appears once however many plugins reference it; built-in ones ship with Claude Code.
1225
+ */
1226
+ function claudePluginInstalls(config$1, home) {
1227
+ const out = [];
1228
+ const added = /* @__PURE__ */ new Set();
1229
+ for (const { marketplace, plugin } of claudePluginDeliveries(config$1)) {
1230
+ const market = config$1.marketplaces[marketplace];
1231
+ if (!market.builtin && !added.has(marketplace)) {
1232
+ added.add(marketplace);
1233
+ out.push({
1234
+ kind: "install",
1235
+ label: `marketplace ${marketplace}`,
1236
+ requires: "claude",
1237
+ command: [
1238
+ "claude",
1239
+ "plugin",
1240
+ "marketplace",
1241
+ "add",
1242
+ market.repo
1243
+ ],
1244
+ probe: {
1245
+ kind: "claude-marketplace",
1246
+ name: marketplace,
1247
+ registryFile: join(home, MARKETPLACE_REGISTRY)
1248
+ }
1249
+ });
1250
+ }
1251
+ const id = `${plugin}@${marketplace}`;
1252
+ out.push({
1253
+ kind: "install",
1254
+ label: id,
1255
+ requires: "claude",
1256
+ command: [
1257
+ "claude",
1258
+ "plugin",
1259
+ "install",
1260
+ id
1261
+ ],
1262
+ probe: {
1263
+ kind: "claude-plugin",
1264
+ id
1265
+ }
1266
+ });
1267
+ }
1268
+ return out;
1269
+ }
1270
+ /**
1271
+ * skills.sh installs into the shared `~/.agents` store. `linkDir` is where the agent expects
1272
+ * to find each skill afterwards — omit it for agents that read the store directly.
1273
+ */
1274
+ function skillInstalls(config$1, agent, home, linkDir) {
1275
+ return skillDeliveries(config$1, agent).map((delivery) => {
1276
+ const command$1 = [
1277
+ "npx",
1278
+ "-y",
1279
+ "skills",
1280
+ "add",
1281
+ delivery.repo,
1282
+ "-g",
1283
+ "-y",
1284
+ "-a",
1285
+ agent
1286
+ ];
1287
+ if (delivery.skills?.length) command$1.push("-s", ...delivery.skills);
1288
+ return {
1289
+ kind: "install",
1290
+ label: `${delivery.repo} (${delivery.skills?.length ?? "all"})`,
1291
+ requires: "npx",
1292
+ command: command$1,
1293
+ probe: {
1294
+ kind: "skills",
1295
+ lockFile: join(home, SKILL_LOCK),
1296
+ names: delivery.skills ?? [],
1297
+ ...linkDir && { linkDir }
1298
+ }
1299
+ };
1300
+ });
1301
+ }
1302
+
1303
+ //#endregion
1304
+ //#region src/commands/setup/agents/store.ts
1305
+ const AGENTS_STORE = ".agents/skills";
1306
+ async function authoredSkillNames(ctx) {
1307
+ return (await readdir(join(ctx.repoRoot, ctx.config.authoredSkillsDir), { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name);
1308
+ }
1309
+ async function buildStorePlan(ctx) {
1310
+ const src = join(ctx.repoRoot, ctx.config.authoredSkillsDir);
1311
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
1312
+ const archiveDir = join(ctx.home, ".agents/.setup-backups", stamp);
1313
+ return {
1314
+ archiveDir,
1315
+ groups: [{
1316
+ section: "Skills store (~/.agents/skills)",
1317
+ artifacts: (await authoredSkillNames(ctx)).map((name$1) => ({
1318
+ kind: "symlink",
1319
+ target: join(src, name$1),
1320
+ linkPath: join(ctx.home, AGENTS_STORE, name$1),
1321
+ archiveDisplaced: join(archiveDir, "skills")
1322
+ }))
1323
+ }]
1324
+ };
1325
+ }
1326
+
1327
+ //#endregion
1328
+ //#region src/commands/setup/agents/emitters/claude-code.ts
1329
+ const CONFIG_DIR$1 = ".claude";
1330
+ const ARCHIVE_DIR = ".setup-backups";
1331
+ const claudeCode = {
1332
+ id: "claude-code",
1333
+ configDir: CONFIG_DIR$1,
1334
+ buildPlan: buildPlan$1
1335
+ };
1336
+ async function buildPlan$1(ctx) {
1337
+ const root = join(ctx.home, CONFIG_DIR$1);
1338
+ const archiveDir = join(root, ARCHIVE_DIR, (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-"));
1339
+ const cc = ctx.config.claudeCode;
1340
+ const statuslinePath = join(root, "statusline-command.sh");
1341
+ const plugins = claudePluginDeliveries(ctx.config);
1342
+ const groups = [
1343
+ {
1344
+ section: "Plugins",
1345
+ artifacts: claudePluginInstalls(ctx.config, ctx.home)
1346
+ },
1347
+ {
1348
+ section: "Skills (remote)",
1349
+ artifacts: skillInstalls(ctx.config, "claude-code", ctx.home, join(root, "skills"))
1350
+ },
1351
+ {
1352
+ section: "Skills (authored)",
1353
+ artifacts: await authoredSkillLinks(ctx, root, archiveDir)
1354
+ },
1355
+ {
1356
+ section: "Instructions & statusline",
1357
+ artifacts: [{
1358
+ kind: "file",
1359
+ src: join(ctx.repoRoot, ctx.config.instructionsFile),
1360
+ dest: join(root, "CLAUDE.md")
1361
+ }, {
1362
+ kind: "file",
1363
+ src: join(ctx.repoRoot, cc.statuslineScript),
1364
+ dest: statuslinePath,
1365
+ mode: 493
1366
+ }]
1367
+ },
1368
+ {
1369
+ section: "settings.json",
1370
+ artifacts: [{
1371
+ kind: "jsonMerge",
1372
+ dest: join(root, "settings.json"),
1373
+ managed: settingsFor(cc),
1374
+ derived: {
1375
+ statusLine: {
1376
+ type: "command",
1377
+ command: `bash ${statuslinePath}`
1378
+ },
1379
+ enabledPlugins: enabledPluginsMap(plugins),
1380
+ extraKnownMarketplaces: marketplacesMap(plugins, ctx.config.marketplaces)
1381
+ }
1382
+ }]
1383
+ }
1384
+ ];
1385
+ const mcpServers = mcpServersFor(ctx.config, "claude-code");
1386
+ if (Object.keys(mcpServers).length) groups.push({
1387
+ section: "~/.claude.json",
1388
+ artifacts: [{
1389
+ kind: "jsonMerge",
1390
+ dest: join(ctx.home, ".claude.json"),
1391
+ managed: {},
1392
+ derived: { mcpServers: mapValues(mcpServers, claudeMcp) }
1393
+ }]
1394
+ });
1395
+ if (cc.commandsDir) groups.push({
1396
+ section: "Commands",
1397
+ artifacts: await commandFiles(ctx.repoRoot, cc.commandsDir, root)
1398
+ });
1399
+ return {
1400
+ archiveDir,
1401
+ groups
1402
+ };
1403
+ }
1404
+ function enabledPluginsMap(deliveries) {
1405
+ return Object.fromEntries(deliveries.map((d) => [`${d.plugin}@${d.marketplace}`, true]));
1406
+ }
1407
+ function marketplacesMap(deliveries, marketplaces) {
1408
+ const referenced = [...new Set(deliveries.map((d) => d.marketplace))];
1409
+ return Object.fromEntries(referenced.filter((name$1) => !marketplaces[name$1].builtin).map((name$1) => [name$1, { source: {
1410
+ source: "github",
1411
+ repo: marketplaces[name$1].repo
1412
+ } }]));
1413
+ }
1414
+ function claudeMcp(server) {
1415
+ return server.transport === "stdio" ? {
1416
+ type: "stdio",
1417
+ command: server.command[0],
1418
+ args: server.command.slice(1),
1419
+ ...server.env && { env: server.env }
1420
+ } : {
1421
+ type: "http",
1422
+ url: server.url,
1423
+ ...server.headers && { headers: server.headers }
1424
+ };
1425
+ }
1426
+ function mapValues(record, fn) {
1427
+ return Object.fromEntries(Object.entries(record).map(([k, v]) => [k, fn(v)]));
1428
+ }
1429
+ async function authoredSkillLinks(ctx, root, archiveDir) {
1430
+ return (await authoredSkillNames(ctx)).map((name$1) => ({
1431
+ kind: "symlink",
1432
+ target: `../../${AGENTS_STORE}/${name$1}`,
1433
+ linkPath: join(root, "skills", name$1),
1434
+ archiveDisplaced: join(archiveDir, "agent-skills")
1435
+ }));
1436
+ }
1437
+ async function commandFiles(repoRoot, dir, root) {
1438
+ const src = resolve(repoRoot, dir);
1439
+ return (await readdir(src)).filter((f) => f.endsWith(".md")).sort().map((f) => ({
1440
+ kind: "file",
1441
+ src: join(src, f),
1442
+ dest: join(root, "commands", f)
1443
+ }));
1444
+ }
1445
+ function settingsFor(cc) {
1446
+ const out = {};
1447
+ if (cc.effort !== void 0) out.effortLevel = cc.effort;
1448
+ if (cc.autoCompactWindow !== void 0) out.autoCompactWindow = cc.autoCompactWindow;
1449
+ if (cc.tui !== void 0) out.tui = cc.tui;
1450
+ if (cc.cleanupPeriodDays !== void 0) out.cleanupPeriodDays = cc.cleanupPeriodDays;
1451
+ if (cc.voice !== void 0) out.voiceEnabled = cc.voice;
1452
+ if (cc.autoDream !== void 0) out.autoDreamEnabled = cc.autoDream;
1453
+ if (cc.agentPushNotifications !== void 0) out.agentPushNotifEnabled = cc.agentPushNotifications;
1454
+ if (cc.permissions?.defaultMode !== void 0) out.permissions = { defaultMode: cc.permissions.defaultMode };
1455
+ if (cc.permissions?.skipDangerousModePrompt !== void 0) out.skipDangerousModePermissionPrompt = cc.permissions.skipDangerousModePrompt;
1456
+ if (cc.permissions?.skipAutoPrompt !== void 0) out.skipAutoPermissionPrompt = cc.permissions.skipAutoPrompt;
1457
+ if (cc.hooks !== void 0) out.hooks = cc.hooks;
1458
+ return out;
1459
+ }
1460
+
1461
+ //#endregion
1462
+ //#region src/commands/setup/agents/emitters/opencode.ts
1463
+ const CONFIG_DIR = ".config/opencode";
1464
+ /** opencode accepts either name; write to whichever already exists so we never fork the config. */
1465
+ const CONFIG_FILES = ["opencode.jsonc", "opencode.json"];
1466
+ const opencode = {
1467
+ id: "opencode",
1468
+ configDir: CONFIG_DIR,
1469
+ buildPlan
1470
+ };
1471
+ async function buildPlan(ctx) {
1472
+ const root = join(ctx.home, CONFIG_DIR);
1473
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
1474
+ const groups = [{
1475
+ section: "Skills (remote)",
1476
+ artifacts: skillInstalls(ctx.config, "opencode", ctx.home)
1477
+ }, {
1478
+ section: "Instructions",
1479
+ artifacts: [{
1480
+ kind: "file",
1481
+ src: join(ctx.repoRoot, ctx.config.instructionsFile),
1482
+ dest: join(root, "AGENTS.md")
1483
+ }]
1484
+ }];
1485
+ const derived = configKeys(ctx.config);
1486
+ if (Object.keys(derived).length) groups.push({
1487
+ section: "opencode config",
1488
+ artifacts: [{
1489
+ kind: "jsonMerge",
1490
+ dest: await configPath(root),
1491
+ managed: {},
1492
+ derived
1493
+ }]
1494
+ });
1495
+ return {
1496
+ archiveDir: join(root, ".setup-backups", stamp),
1497
+ groups
1498
+ };
1499
+ }
1500
+ async function configPath(root) {
1501
+ for (const name$1 of CONFIG_FILES) if (await exists(join(root, name$1))) return join(root, name$1);
1502
+ return join(root, CONFIG_FILES[1]);
1503
+ }
1504
+ function configKeys(config$1) {
1505
+ const out = {};
1506
+ const plugin = opencodePluginPackages(config$1);
1507
+ if (plugin.length) out.plugin = plugin;
1508
+ const servers = Object.entries(mcpServersFor(config$1, "opencode"));
1509
+ if (servers.length) out.mcp = Object.fromEntries(servers.map(([name$1, server]) => [name$1, opencodeMcp(server)]));
1510
+ return out;
1511
+ }
1512
+ function opencodeMcp(server) {
1513
+ return server.transport === "stdio" ? {
1514
+ type: "local",
1515
+ command: server.command,
1516
+ enabled: true,
1517
+ ...server.env && { environment: server.env }
1518
+ } : {
1519
+ type: "remote",
1520
+ url: server.url,
1521
+ enabled: true,
1522
+ ...server.headers && { headers: server.headers }
1523
+ };
1524
+ }
1525
+
1526
+ //#endregion
1527
+ //#region src/commands/setup/agents/emitters/index.ts
1528
+ const emitters = {
1529
+ "claude-code": claudeCode,
1530
+ opencode,
1531
+ codex: null
1532
+ };
1533
+
1534
+ //#endregion
1535
+ //#region src/util/exec.ts
1536
+ function run(cmd) {
1537
+ return new Promise((resolve$1) => {
1538
+ const [bin, ...args] = cmd;
1539
+ const proc = spawn(bin, args);
1540
+ let stdout$1 = "";
1541
+ let stderr = "";
1542
+ proc.stdout.on("data", (d) => stdout$1 += d);
1543
+ proc.stderr.on("data", (d) => stderr += d);
1544
+ proc.on("error", () => resolve$1({
1545
+ ok: false,
1546
+ stdout: stdout$1,
1547
+ stderr
1548
+ }));
1549
+ proc.on("close", (code) => resolve$1({
1550
+ ok: code === 0,
1551
+ stdout: stdout$1,
1552
+ stderr
1553
+ }));
1554
+ });
1555
+ }
1556
+ async function which(bin) {
1557
+ return (await run([
1558
+ "sh",
1559
+ "-c",
1560
+ `command -v ${bin}`
1561
+ ])).ok;
1562
+ }
1563
+
1564
+ //#endregion
1565
+ //#region src/commands/setup/agents/diff.ts
1566
+ async function diff(plan) {
1567
+ const probes = new Probes();
1568
+ const sections = [];
1569
+ for (const group of plan.groups) {
1570
+ const changes = [];
1571
+ for (const artifact of group.artifacts) changes.push(await changeFor(artifact, plan.archiveDir, probes));
1572
+ sections.push({
1573
+ title: group.section,
1574
+ changes
1575
+ });
1576
+ }
1577
+ return sections;
1578
+ }
1579
+ function changeFor(a$1, archiveDir, probes) {
1580
+ switch (a$1.kind) {
1581
+ case "file": return fileChange(a$1);
1582
+ case "symlink": return symlinkChange(a$1);
1583
+ case "jsonMerge": return jsonMergeChange(a$1, archiveDir);
1584
+ case "install": return installChange(a$1, probes);
1585
+ }
1586
+ }
1587
+ async function fileChange(a$1) {
1588
+ const next = await readFile(a$1.src);
1589
+ if ((await readFile(a$1.dest).catch(() => null))?.equals(next)) return {
1590
+ status: "unchanged",
1591
+ label: a$1.dest
1592
+ };
1593
+ return {
1594
+ status: "pending",
1595
+ label: a$1.dest,
1596
+ action: {
1597
+ do: "write-file",
1598
+ src: a$1.src,
1599
+ dest: a$1.dest,
1600
+ ...a$1.mode && { mode: a$1.mode }
1601
+ }
1602
+ };
1603
+ }
1604
+ async function symlinkChange(a$1) {
1605
+ const label = `${a$1.linkPath} → ${a$1.target}`;
1606
+ const link = {
1607
+ do: "link",
1608
+ target: a$1.target,
1609
+ linkPath: a$1.linkPath
1610
+ };
1611
+ if (!await exists(a$1.linkPath)) return {
1612
+ status: "pending",
1613
+ label,
1614
+ action: link
1615
+ };
1616
+ if ((await lstat(a$1.linkPath)).isSymbolicLink()) {
1617
+ if (await readlink(a$1.linkPath) === a$1.target) return {
1618
+ status: "unchanged",
1619
+ label
1620
+ };
1621
+ return {
1622
+ status: "pending",
1623
+ label,
1624
+ action: {
1625
+ ...link,
1626
+ removeExisting: true
1627
+ }
1628
+ };
1629
+ }
1630
+ if (!a$1.archiveDisplaced) return {
1631
+ status: "blocked",
1632
+ label,
1633
+ reason: `${a$1.linkPath} exists as a real directory`
1634
+ };
1635
+ const archiveTo = join(a$1.archiveDisplaced, basename(a$1.linkPath));
1636
+ return {
1637
+ status: "pending",
1638
+ label,
1639
+ action: {
1640
+ ...link,
1641
+ archiveTo
1642
+ }
1643
+ };
1644
+ }
1645
+ async function jsonMergeChange(a$1, archiveDir) {
1646
+ const label = basename(a$1.dest);
1647
+ const raw = await readFile(a$1.dest, "utf8").catch(() => null);
1648
+ let current = {};
1649
+ if (raw !== null) try {
1650
+ current = JSON.parse(raw);
1651
+ } catch {
1652
+ return {
1653
+ status: "blocked",
1654
+ label,
1655
+ reason: "not parseable JSON (comments?)"
1656
+ };
1657
+ }
1658
+ const value = {
1659
+ ...current,
1660
+ ...a$1.managed,
1661
+ ...a$1.derived
1662
+ };
1663
+ if (stable(current) === stable(value)) return {
1664
+ status: "unchanged",
1665
+ label
1666
+ };
1667
+ const notes = Object.keys(value).filter((k) => stable(current[k]) !== stable(value[k])).map((k) => `set ${k}${k in a$1.derived ? " (derived)" : ""}`);
1668
+ const unmanaged = Object.keys(current).filter((k) => !(k in a$1.managed) && !(k in a$1.derived));
1669
+ if (unmanaged.length) notes.push(`preserved unmanaged keys: ${unmanaged.join(", ")}`);
1670
+ return {
1671
+ status: "pending",
1672
+ label,
1673
+ action: {
1674
+ do: "write-json",
1675
+ dest: a$1.dest,
1676
+ value,
1677
+ backupTo: archiveDir
1678
+ },
1679
+ notes
1680
+ };
1681
+ }
1682
+ async function installChange(a$1, probes) {
1683
+ if (!await probes.onPath(a$1.requires)) return {
1684
+ status: "blocked",
1685
+ label: a$1.label,
1686
+ reason: `\`${a$1.requires}\` not on PATH`
1687
+ };
1688
+ if (await probes.satisfied(a$1.probe)) return {
1689
+ status: "unchanged",
1690
+ label: a$1.label
1691
+ };
1692
+ return {
1693
+ status: "pending",
1694
+ label: a$1.label,
1695
+ action: {
1696
+ do: "run",
1697
+ command: a$1.command
1698
+ }
1699
+ };
1700
+ }
1701
+ /** Memoised machine lookups — `claude plugin list` costs a process spawn, so it runs once. */
1702
+ var Probes = class {
1703
+ onPathCache = /* @__PURE__ */ new Map();
1704
+ jsonCache = /* @__PURE__ */ new Map();
1705
+ plugins;
1706
+ onPath(bin) {
1707
+ let hit = this.onPathCache.get(bin);
1708
+ if (!hit) this.onPathCache.set(bin, hit = which(bin));
1709
+ return hit;
1710
+ }
1711
+ async satisfied(probe) {
1712
+ switch (probe.kind) {
1713
+ case "claude-plugin": return (await this.installedPlugins()).has(probe.id);
1714
+ case "claude-marketplace": {
1715
+ const registry = await this.json(probe.registryFile);
1716
+ return !!registry && probe.name in registry;
1717
+ }
1718
+ case "skills": {
1719
+ if (!probe.names.length) return false;
1720
+ const skills = (await this.json(probe.lockFile))?.skills ?? {};
1721
+ for (const name$1 of probe.names) {
1722
+ if (!(name$1 in skills)) return false;
1723
+ if (probe.linkDir && !await exists(join(probe.linkDir, name$1))) return false;
1724
+ }
1725
+ return true;
1726
+ }
1727
+ }
1728
+ }
1729
+ installedPlugins() {
1730
+ this.plugins ??= run([
1731
+ "claude",
1732
+ "plugin",
1733
+ "list"
1734
+ ]).then((res) => new Set(res.stdout.match(/[\w.-]+@[\w.-]+/g) ?? []));
1735
+ return this.plugins;
1736
+ }
1737
+ json(file) {
1738
+ let hit = this.jsonCache.get(file);
1739
+ if (!hit) {
1740
+ hit = readFile(file, "utf8").then((raw) => {
1741
+ try {
1742
+ return JSON.parse(raw);
1743
+ } catch {
1744
+ return null;
1745
+ }
1746
+ }, () => null);
1747
+ this.jsonCache.set(file, hit);
1748
+ }
1749
+ return hit;
1750
+ }
1751
+ };
1752
+
1753
+ //#endregion
1754
+ //#region src/commands/setup/agents/executor.ts
1755
+ /** The one place `dryRun` is consulted: the same diff is either printed or committed. */
1756
+ async function runPlan(plan, dryRun) {
1757
+ await walk(await diff(plan), dryRun ? render : commit);
1758
+ }
1759
+ async function walk(sections, handle) {
1760
+ for (const { title, changes } of sections) {
1761
+ log.section(title);
1762
+ for (const change of changes) await handle(change);
1763
+ }
1764
+ }
1765
+ function render(change) {
1766
+ switch (change.status) {
1767
+ case "unchanged": return log.skip(`${change.label} (unchanged)`);
1768
+ case "blocked": return log.warn(`${change.label} — ${change.reason}, leaving it alone`);
1769
+ case "pending":
1770
+ log.plan(phrase(change.action));
1771
+ for (const note of change.notes ?? []) log.info(note);
1772
+ }
1773
+ }
1774
+ async function commit(change) {
1775
+ switch (change.status) {
1776
+ case "unchanged": return log.skip(`${change.label} (unchanged)`);
1777
+ case "blocked": return log.fail(`${change.label} — ${change.reason}, leaving it alone`);
1778
+ case "pending": {
1779
+ const { ok, notes } = await perform(change.action);
1780
+ if (!ok) return log.fail(`${change.label}: ${notes.join(" ")}`);
1781
+ log.ok(change.label);
1782
+ for (const note of [...notes, ...change.notes ?? []]) log.info(note);
1783
+ }
1784
+ }
1785
+ }
1786
+ async function perform(action) {
1787
+ switch (action.do) {
1788
+ case "write-file": {
1789
+ const bytes = await readFile(action.src);
1790
+ await ensureDir(dirname(action.dest));
1791
+ await writeFile(action.dest, bytes, action.mode ? { mode: action.mode } : void 0);
1792
+ return {
1793
+ ok: true,
1794
+ notes: []
1795
+ };
1796
+ }
1797
+ case "link": {
1798
+ const notes = [];
1799
+ if (action.archiveTo) {
1800
+ await ensureDir(dirname(action.archiveTo));
1801
+ await rename(action.linkPath, action.archiveTo);
1802
+ notes.push(`archived → ${action.archiveTo}`);
1803
+ } else if (action.removeExisting) await rm(action.linkPath, {
1804
+ recursive: true,
1805
+ force: true
1806
+ });
1807
+ await ensureDir(dirname(action.linkPath));
1808
+ await symlink(action.target, action.linkPath);
1809
+ return {
1810
+ ok: true,
1811
+ notes
1812
+ };
1813
+ }
1814
+ case "write-json": {
1815
+ const bak = await backup(action.dest, action.backupTo);
1816
+ await writeJson(action.dest, action.value);
1817
+ return {
1818
+ ok: true,
1819
+ notes: bak ? [`backed up → ${bak}`] : []
1820
+ };
1821
+ }
1822
+ case "run": {
1823
+ const res = await run(action.command);
1824
+ const output = res.stdout + res.stderr;
1825
+ if (res.ok) return {
1826
+ ok: true,
1827
+ notes: []
1828
+ };
1829
+ if (/already/i.test(output)) return {
1830
+ ok: true,
1831
+ notes: ["already present"]
1832
+ };
1833
+ return {
1834
+ ok: false,
1835
+ notes: [output.trim().split("\n").slice(-1)[0] ?? "failed"]
1836
+ };
1837
+ }
1838
+ }
1839
+ }
1840
+ function phrase(action) {
1841
+ switch (action.do) {
1842
+ case "write-file": return `write ${action.dest}`;
1843
+ case "link":
1844
+ if (action.archiveTo) return `archive ${action.linkPath} → ${action.archiveTo}, then link`;
1845
+ return `${action.removeExisting ? "relink" : "link"} ${action.linkPath} → ${action.target}`;
1846
+ case "write-json": return `write ${action.dest}`;
1847
+ case "run": return action.command.join(" ");
1848
+ }
1849
+ }
1850
+
1851
+ //#endregion
1852
+ //#region src/commands/setup/agents/apply.ts
1853
+ /** An agent with no config directory is not on this machine — skip it, never create it. */
1854
+ function isInstalled(home, emitter) {
1855
+ return exists(join(home, emitter.configDir));
1856
+ }
1857
+ async function applyAgents(ctx, ids, dryRun) {
1858
+ validateExtensions(ctx.config);
1859
+ logCoverage(ctx.config);
1860
+ await runPlan(await buildStorePlan(ctx), dryRun);
1861
+ for (const id of ids) {
1862
+ const emitter = emitters[id];
1863
+ if (!emitter) continue;
1864
+ log.agent(id);
1865
+ if (!await isInstalled(ctx.home, emitter)) {
1866
+ log.warn(`${id} not installed on this machine — skipping`);
1867
+ continue;
1868
+ }
1869
+ await runPlan(await emitter.buildPlan(ctx), dryRun);
1870
+ }
1871
+ }
1872
+
1873
+ //#endregion
1874
+ //#region src/commands/setup/agents/index.ts
1875
+ var import_picocolors$2 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
1876
+ const USAGE$1 = `Usage: pakhale setup agents [plan] [options]
1877
+
1878
+ Apply the coding-agent workflow (plugins, skills, settings) to this machine.
1879
+ With a terminal and no --agent, you are asked which agents to apply to; piped or
1880
+ scripted runs apply to every configured agent.
1881
+
1882
+ plan dry run — show every change, write nothing
1883
+
1884
+ Options:
1885
+ -n, --dry-run same as plan
1886
+ -a, --agent <id> target one agent (repeatable) — skips the prompt
1887
+ --all every configured agent — skips the prompt
1888
+ --home <dir> apply against a different home directory
1889
+ -h, --help show this help`;
1890
+ const agents = {
1891
+ name: "agents",
1892
+ describe: "apply the coding-agent workflow (plugins, skills, settings) to this machine",
1893
+ async run(argv$1, packageRoot$1) {
1894
+ const { values, positionals } = parseArgs({
1895
+ args: argv$1,
1896
+ options: {
1897
+ "dry-run": {
1898
+ type: "boolean",
1899
+ short: "n",
1900
+ default: false
1901
+ },
1902
+ agent: {
1903
+ type: "string",
1904
+ short: "a",
1905
+ multiple: true
1906
+ },
1907
+ all: {
1908
+ type: "boolean",
1909
+ default: false
1910
+ },
1911
+ home: { type: "string" },
1912
+ help: {
1913
+ type: "boolean",
1914
+ short: "h",
1915
+ default: false
1916
+ }
1917
+ },
1918
+ allowPositionals: true
1919
+ });
1920
+ if (values.help) {
1921
+ console.log(USAGE$1);
1922
+ return 0;
1923
+ }
1924
+ const dryRun = values["dry-run"] || positionals.includes("plan");
1925
+ const home = values.home ? resolve(values.home) : homedir();
1926
+ const only = values.agent ?? [];
1927
+ const available = (only.length ? only : config.agents).filter((id) => {
1928
+ if (emitters[id]) return true;
1929
+ log.warn(`no emitter for "${id}" yet — skipping`);
1930
+ return false;
1931
+ });
1932
+ const selected = shouldAsk({
1933
+ requested: only.length,
1934
+ all: values.all,
1935
+ interactive: isInteractive()
1936
+ }) ? await chooseAgents(available, home) : available;
1937
+ if (!selected.length) {
1938
+ log.fail("nothing to do");
1939
+ return 1;
1940
+ }
1941
+ const mode = dryRun ? ` ${import_picocolors$2.default.yellow("(dry run)")}` : "";
1942
+ const where = home === homedir() ? "" : ` ${import_picocolors$2.default.magenta(`[home=${home}]`)}`;
1943
+ console.log(`\npakhale setup agents${mode}${where} → ${selected.join(", ")}`);
1944
+ await applyAgents({
1945
+ home,
1946
+ repoRoot: packageRoot$1,
1947
+ config
1948
+ }, selected, dryRun);
1949
+ console.log(dryRun ? `\n${import_picocolors$2.default.yellow("dry run complete — nothing written")}\n` : `\n${import_picocolors$2.default.green("done")}\n`);
1950
+ return 0;
1951
+ }
1952
+ };
1953
+ async function chooseAgents(ids, home) {
1954
+ return await multiSelect("Which agents?", await Promise.all(ids.map(async (id) => ({
1955
+ value: id,
1956
+ label: id,
1957
+ hint: await isInstalled(home, emitters[id]) ? "" : "not installed here"
1958
+ }))));
1959
+ }
1960
+
1961
+ //#endregion
1962
+ //#region src/commands/setup/index.ts
1963
+ var import_picocolors$1 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
1964
+ /** One entry per thing this machine can be set up from `config.ts`. */
1965
+ const targets = { [agents.name]: agents };
1966
+ const USAGE = `Usage: pakhale setup <target> [options]
1967
+
1968
+ Set up part of this machine from the declarations in config.ts.
1969
+
1970
+ Targets:
1971
+ ${Object.values(targets).map((t) => ` ${t.name.padEnd(10)} ${t.describe}`).join("\n")}
1972
+
1973
+ Run \`pakhale setup <target> --help\` for a target's own options.`;
1974
+ const setup = {
1975
+ name: "setup",
1976
+ describe: "set up this machine from config.ts",
1977
+ async run(argv$1, packageRoot$1) {
1978
+ const [name$1, ...rest$1] = argv$1;
1979
+ if (!name$1) {
1980
+ console.error(import_picocolors$1.default.red("setup needs a target\n"));
1981
+ console.log(USAGE);
1982
+ return 1;
1983
+ }
1984
+ if (name$1 === "--help" || name$1 === "-h") {
1985
+ console.log(USAGE);
1986
+ return 0;
1987
+ }
1988
+ const target = targets[name$1];
1989
+ if (!target) {
1990
+ console.error(import_picocolors$1.default.red(`unknown setup target: ${name$1}\n`));
1991
+ console.log(USAGE);
1992
+ return 1;
1993
+ }
1994
+ return target.run(rest$1, packageRoot$1);
1995
+ }
1996
+ };
1997
+
1998
+ //#endregion
1999
+ //#region src/commands/index.ts
2000
+ const commands = { [setup.name]: setup };
2001
+
2002
+ //#endregion
2003
+ //#region src/cli.ts
2004
+ var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
2005
+ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
2006
+ const [name, ...rest] = process.argv.slice(2);
2007
+ async function version() {
2008
+ return JSON.parse(await readFile(join(packageRoot, "package.json"), "utf8")).version;
2009
+ }
2010
+ function usage() {
2011
+ console.log(`Usage: pakhale <command> [options]\n\nCommands:`);
2012
+ for (const c of Object.values(commands)) console.log(` ${c.name.padEnd(10)} ${c.describe}`);
2013
+ console.log(`\nOptions:\n -h, --help show this help\n -v, --version show version`);
2014
+ }
2015
+ if (!name || name === "--help" || name === "-h") {
2016
+ usage();
2017
+ process.exit(0);
2018
+ }
2019
+ if (name === "--version" || name === "-v") {
2020
+ console.log(await version());
2021
+ process.exit(0);
2022
+ }
2023
+ const command = commands[name];
2024
+ if (!command) {
2025
+ console.error(import_picocolors.default.red(`unknown command: ${name}\n`));
2026
+ usage();
2027
+ process.exit(1);
2028
+ }
2029
+ try {
2030
+ process.exit(await command.run(rest, packageRoot));
2031
+ } catch (err) {
2032
+ console.error(import_picocolors.default.red(err instanceof Error ? err.message : String(err)));
2033
+ process.exit(1);
2034
+ }
2035
+
2036
+ //#endregion
2037
+ export { };