@wbern/claude-instructions 1.8.1 → 1.10.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/LICENSE +21 -0
- package/README.md +21 -11
- package/bin/cli.js +796 -47
- package/downloads/with-beads/ask.md +1 -4
- package/downloads/with-beads/beepboop.md +0 -1
- package/downloads/with-beads/busycommit.md +16 -1
- package/downloads/with-beads/code-review.md +248 -0
- package/downloads/with-beads/commands-metadata.json +57 -15
- package/downloads/with-beads/commit.md +16 -1
- package/downloads/with-beads/cycle.md +0 -1
- package/downloads/with-beads/gap.md +1 -0
- package/downloads/with-beads/green.md +0 -1
- package/downloads/with-beads/issue.md +0 -1
- package/downloads/with-beads/plan.md +1 -3
- package/downloads/with-beads/pr.md +82 -0
- package/downloads/with-beads/red.md +0 -1
- package/downloads/with-beads/refactor.md +0 -1
- package/downloads/with-beads/ship.md +1 -4
- package/downloads/with-beads/show.md +1 -4
- package/downloads/with-beads/spike.md +0 -1
- package/downloads/with-beads/summarize.md +0 -1
- package/downloads/with-beads/tdd.md +0 -1
- package/downloads/with-beads/worktree-add.md +0 -1
- package/downloads/with-beads/worktree-cleanup.md +0 -1
- package/downloads/without-beads/ask.md +1 -4
- package/downloads/without-beads/beepboop.md +0 -1
- package/downloads/without-beads/busycommit.md +16 -1
- package/downloads/without-beads/code-review.md +246 -0
- package/downloads/without-beads/commands-metadata.json +57 -15
- package/downloads/without-beads/commit.md +16 -1
- package/downloads/without-beads/cycle.md +0 -1
- package/downloads/without-beads/gap.md +1 -0
- package/downloads/without-beads/green.md +0 -1
- package/downloads/without-beads/issue.md +0 -1
- package/downloads/without-beads/plan.md +0 -1
- package/downloads/without-beads/pr.md +70 -0
- package/downloads/without-beads/red.md +0 -1
- package/downloads/without-beads/refactor.md +0 -1
- package/downloads/without-beads/ship.md +1 -4
- package/downloads/without-beads/show.md +1 -4
- package/downloads/without-beads/spike.md +0 -1
- package/downloads/without-beads/summarize.md +0 -1
- package/downloads/without-beads/tdd.md +0 -1
- package/downloads/without-beads/worktree-add.md +0 -1
- package/downloads/without-beads/worktree-cleanup.md +0 -1
- package/package.json +7 -3
package/bin/cli.js
CHANGED
|
@@ -1,16 +1,401 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
11
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
12
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
13
|
+
};
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
+
for (let key of __getOwnPropNames(from))
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
23
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
24
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
25
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
26
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
27
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
28
|
+
mod
|
|
29
|
+
));
|
|
30
|
+
|
|
31
|
+
// node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/esm_shims.js
|
|
32
|
+
import path from "path";
|
|
33
|
+
import { fileURLToPath } from "url";
|
|
34
|
+
var init_esm_shims = __esm({
|
|
35
|
+
"node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/esm_shims.js"() {
|
|
36
|
+
"use strict";
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js
|
|
41
|
+
var require_picocolors = __commonJS({
|
|
42
|
+
"node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js"(exports, module) {
|
|
43
|
+
"use strict";
|
|
44
|
+
init_esm_shims();
|
|
45
|
+
var p = process || {};
|
|
46
|
+
var argv = p.argv || [];
|
|
47
|
+
var env = p.env || {};
|
|
48
|
+
var 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);
|
|
49
|
+
var formatter = (open, close, replace = open) => (input) => {
|
|
50
|
+
let string = "" + input, index = string.indexOf(close, open.length);
|
|
51
|
+
return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
|
|
52
|
+
};
|
|
53
|
+
var replaceClose = (string, close, replace, index) => {
|
|
54
|
+
let result = "", cursor = 0;
|
|
55
|
+
do {
|
|
56
|
+
result += string.substring(cursor, index) + replace;
|
|
57
|
+
cursor = index + close.length;
|
|
58
|
+
index = string.indexOf(close, cursor);
|
|
59
|
+
} while (~index);
|
|
60
|
+
return result + string.substring(cursor);
|
|
61
|
+
};
|
|
62
|
+
var createColors = (enabled = isColorSupported) => {
|
|
63
|
+
let f = enabled ? formatter : () => String;
|
|
64
|
+
return {
|
|
65
|
+
isColorSupported: enabled,
|
|
66
|
+
reset: f("\x1B[0m", "\x1B[0m"),
|
|
67
|
+
bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
|
|
68
|
+
dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
|
|
69
|
+
italic: f("\x1B[3m", "\x1B[23m"),
|
|
70
|
+
underline: f("\x1B[4m", "\x1B[24m"),
|
|
71
|
+
inverse: f("\x1B[7m", "\x1B[27m"),
|
|
72
|
+
hidden: f("\x1B[8m", "\x1B[28m"),
|
|
73
|
+
strikethrough: f("\x1B[9m", "\x1B[29m"),
|
|
74
|
+
black: f("\x1B[30m", "\x1B[39m"),
|
|
75
|
+
red: f("\x1B[31m", "\x1B[39m"),
|
|
76
|
+
green: f("\x1B[32m", "\x1B[39m"),
|
|
77
|
+
yellow: f("\x1B[33m", "\x1B[39m"),
|
|
78
|
+
blue: f("\x1B[34m", "\x1B[39m"),
|
|
79
|
+
magenta: f("\x1B[35m", "\x1B[39m"),
|
|
80
|
+
cyan: f("\x1B[36m", "\x1B[39m"),
|
|
81
|
+
white: f("\x1B[37m", "\x1B[39m"),
|
|
82
|
+
gray: f("\x1B[90m", "\x1B[39m"),
|
|
83
|
+
bgBlack: f("\x1B[40m", "\x1B[49m"),
|
|
84
|
+
bgRed: f("\x1B[41m", "\x1B[49m"),
|
|
85
|
+
bgGreen: f("\x1B[42m", "\x1B[49m"),
|
|
86
|
+
bgYellow: f("\x1B[43m", "\x1B[49m"),
|
|
87
|
+
bgBlue: f("\x1B[44m", "\x1B[49m"),
|
|
88
|
+
bgMagenta: f("\x1B[45m", "\x1B[49m"),
|
|
89
|
+
bgCyan: f("\x1B[46m", "\x1B[49m"),
|
|
90
|
+
bgWhite: f("\x1B[47m", "\x1B[49m"),
|
|
91
|
+
blackBright: f("\x1B[90m", "\x1B[39m"),
|
|
92
|
+
redBright: f("\x1B[91m", "\x1B[39m"),
|
|
93
|
+
greenBright: f("\x1B[92m", "\x1B[39m"),
|
|
94
|
+
yellowBright: f("\x1B[93m", "\x1B[39m"),
|
|
95
|
+
blueBright: f("\x1B[94m", "\x1B[39m"),
|
|
96
|
+
magentaBright: f("\x1B[95m", "\x1B[39m"),
|
|
97
|
+
cyanBright: f("\x1B[96m", "\x1B[39m"),
|
|
98
|
+
whiteBright: f("\x1B[97m", "\x1B[39m"),
|
|
99
|
+
bgBlackBright: f("\x1B[100m", "\x1B[49m"),
|
|
100
|
+
bgRedBright: f("\x1B[101m", "\x1B[49m"),
|
|
101
|
+
bgGreenBright: f("\x1B[102m", "\x1B[49m"),
|
|
102
|
+
bgYellowBright: f("\x1B[103m", "\x1B[49m"),
|
|
103
|
+
bgBlueBright: f("\x1B[104m", "\x1B[49m"),
|
|
104
|
+
bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
|
|
105
|
+
bgCyanBright: f("\x1B[106m", "\x1B[49m"),
|
|
106
|
+
bgWhiteBright: f("\x1B[107m", "\x1B[49m")
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
module.exports = createColors();
|
|
110
|
+
module.exports.createColors = createColors;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// scripts/bin.ts
|
|
115
|
+
init_esm_shims();
|
|
2
116
|
|
|
3
117
|
// scripts/cli.ts
|
|
4
|
-
|
|
118
|
+
init_esm_shims();
|
|
119
|
+
import {
|
|
120
|
+
select,
|
|
121
|
+
text,
|
|
122
|
+
multiselect,
|
|
123
|
+
groupMultiselect,
|
|
124
|
+
isCancel,
|
|
125
|
+
intro,
|
|
126
|
+
outro,
|
|
127
|
+
confirm,
|
|
128
|
+
note,
|
|
129
|
+
log
|
|
130
|
+
} from "@clack/prompts";
|
|
5
131
|
import os2 from "os";
|
|
6
132
|
|
|
133
|
+
// node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/index.js
|
|
134
|
+
init_esm_shims();
|
|
135
|
+
|
|
136
|
+
// node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/diff/base.js
|
|
137
|
+
init_esm_shims();
|
|
138
|
+
var Diff = class {
|
|
139
|
+
diff(oldStr, newStr, options = {}) {
|
|
140
|
+
let callback;
|
|
141
|
+
if (typeof options === "function") {
|
|
142
|
+
callback = options;
|
|
143
|
+
options = {};
|
|
144
|
+
} else if ("callback" in options) {
|
|
145
|
+
callback = options.callback;
|
|
146
|
+
}
|
|
147
|
+
const oldString = this.castInput(oldStr, options);
|
|
148
|
+
const newString = this.castInput(newStr, options);
|
|
149
|
+
const oldTokens = this.removeEmpty(this.tokenize(oldString, options));
|
|
150
|
+
const newTokens = this.removeEmpty(this.tokenize(newString, options));
|
|
151
|
+
return this.diffWithOptionsObj(oldTokens, newTokens, options, callback);
|
|
152
|
+
}
|
|
153
|
+
diffWithOptionsObj(oldTokens, newTokens, options, callback) {
|
|
154
|
+
var _a;
|
|
155
|
+
const done = (value) => {
|
|
156
|
+
value = this.postProcess(value, options);
|
|
157
|
+
if (callback) {
|
|
158
|
+
setTimeout(function() {
|
|
159
|
+
callback(value);
|
|
160
|
+
}, 0);
|
|
161
|
+
return void 0;
|
|
162
|
+
} else {
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const newLen = newTokens.length, oldLen = oldTokens.length;
|
|
167
|
+
let editLength = 1;
|
|
168
|
+
let maxEditLength = newLen + oldLen;
|
|
169
|
+
if (options.maxEditLength != null) {
|
|
170
|
+
maxEditLength = Math.min(maxEditLength, options.maxEditLength);
|
|
171
|
+
}
|
|
172
|
+
const maxExecutionTime = (_a = options.timeout) !== null && _a !== void 0 ? _a : Infinity;
|
|
173
|
+
const abortAfterTimestamp = Date.now() + maxExecutionTime;
|
|
174
|
+
const bestPath = [{ oldPos: -1, lastComponent: void 0 }];
|
|
175
|
+
let newPos = this.extractCommon(bestPath[0], newTokens, oldTokens, 0, options);
|
|
176
|
+
if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
|
|
177
|
+
return done(this.buildValues(bestPath[0].lastComponent, newTokens, oldTokens));
|
|
178
|
+
}
|
|
179
|
+
let minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
|
|
180
|
+
const execEditLength = () => {
|
|
181
|
+
for (let diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
|
|
182
|
+
let basePath;
|
|
183
|
+
const removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
|
|
184
|
+
if (removePath) {
|
|
185
|
+
bestPath[diagonalPath - 1] = void 0;
|
|
186
|
+
}
|
|
187
|
+
let canAdd = false;
|
|
188
|
+
if (addPath) {
|
|
189
|
+
const addPathNewPos = addPath.oldPos - diagonalPath;
|
|
190
|
+
canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
|
|
191
|
+
}
|
|
192
|
+
const canRemove = removePath && removePath.oldPos + 1 < oldLen;
|
|
193
|
+
if (!canAdd && !canRemove) {
|
|
194
|
+
bestPath[diagonalPath] = void 0;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) {
|
|
198
|
+
basePath = this.addToPath(addPath, true, false, 0, options);
|
|
199
|
+
} else {
|
|
200
|
+
basePath = this.addToPath(removePath, false, true, 1, options);
|
|
201
|
+
}
|
|
202
|
+
newPos = this.extractCommon(basePath, newTokens, oldTokens, diagonalPath, options);
|
|
203
|
+
if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
|
|
204
|
+
return done(this.buildValues(basePath.lastComponent, newTokens, oldTokens)) || true;
|
|
205
|
+
} else {
|
|
206
|
+
bestPath[diagonalPath] = basePath;
|
|
207
|
+
if (basePath.oldPos + 1 >= oldLen) {
|
|
208
|
+
maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
|
|
209
|
+
}
|
|
210
|
+
if (newPos + 1 >= newLen) {
|
|
211
|
+
minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
editLength++;
|
|
216
|
+
};
|
|
217
|
+
if (callback) {
|
|
218
|
+
(function exec() {
|
|
219
|
+
setTimeout(function() {
|
|
220
|
+
if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
|
|
221
|
+
return callback(void 0);
|
|
222
|
+
}
|
|
223
|
+
if (!execEditLength()) {
|
|
224
|
+
exec();
|
|
225
|
+
}
|
|
226
|
+
}, 0);
|
|
227
|
+
})();
|
|
228
|
+
} else {
|
|
229
|
+
while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
|
|
230
|
+
const ret = execEditLength();
|
|
231
|
+
if (ret) {
|
|
232
|
+
return ret;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
addToPath(path3, added, removed, oldPosInc, options) {
|
|
238
|
+
const last = path3.lastComponent;
|
|
239
|
+
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
240
|
+
return {
|
|
241
|
+
oldPos: path3.oldPos + oldPosInc,
|
|
242
|
+
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
243
|
+
};
|
|
244
|
+
} else {
|
|
245
|
+
return {
|
|
246
|
+
oldPos: path3.oldPos + oldPosInc,
|
|
247
|
+
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
extractCommon(basePath, newTokens, oldTokens, diagonalPath, options) {
|
|
252
|
+
const newLen = newTokens.length, oldLen = oldTokens.length;
|
|
253
|
+
let oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
|
|
254
|
+
while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldTokens[oldPos + 1], newTokens[newPos + 1], options)) {
|
|
255
|
+
newPos++;
|
|
256
|
+
oldPos++;
|
|
257
|
+
commonCount++;
|
|
258
|
+
if (options.oneChangePerToken) {
|
|
259
|
+
basePath.lastComponent = { count: 1, previousComponent: basePath.lastComponent, added: false, removed: false };
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (commonCount && !options.oneChangePerToken) {
|
|
263
|
+
basePath.lastComponent = { count: commonCount, previousComponent: basePath.lastComponent, added: false, removed: false };
|
|
264
|
+
}
|
|
265
|
+
basePath.oldPos = oldPos;
|
|
266
|
+
return newPos;
|
|
267
|
+
}
|
|
268
|
+
equals(left, right, options) {
|
|
269
|
+
if (options.comparator) {
|
|
270
|
+
return options.comparator(left, right);
|
|
271
|
+
} else {
|
|
272
|
+
return left === right || !!options.ignoreCase && left.toLowerCase() === right.toLowerCase();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
removeEmpty(array) {
|
|
276
|
+
const ret = [];
|
|
277
|
+
for (let i = 0; i < array.length; i++) {
|
|
278
|
+
if (array[i]) {
|
|
279
|
+
ret.push(array[i]);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return ret;
|
|
283
|
+
}
|
|
284
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
285
|
+
castInput(value, options) {
|
|
286
|
+
return value;
|
|
287
|
+
}
|
|
288
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
289
|
+
tokenize(value, options) {
|
|
290
|
+
return Array.from(value);
|
|
291
|
+
}
|
|
292
|
+
join(chars) {
|
|
293
|
+
return chars.join("");
|
|
294
|
+
}
|
|
295
|
+
postProcess(changeObjects, options) {
|
|
296
|
+
return changeObjects;
|
|
297
|
+
}
|
|
298
|
+
get useLongestToken() {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
buildValues(lastComponent, newTokens, oldTokens) {
|
|
302
|
+
const components = [];
|
|
303
|
+
let nextComponent;
|
|
304
|
+
while (lastComponent) {
|
|
305
|
+
components.push(lastComponent);
|
|
306
|
+
nextComponent = lastComponent.previousComponent;
|
|
307
|
+
delete lastComponent.previousComponent;
|
|
308
|
+
lastComponent = nextComponent;
|
|
309
|
+
}
|
|
310
|
+
components.reverse();
|
|
311
|
+
const componentLen = components.length;
|
|
312
|
+
let componentPos = 0, newPos = 0, oldPos = 0;
|
|
313
|
+
for (; componentPos < componentLen; componentPos++) {
|
|
314
|
+
const component = components[componentPos];
|
|
315
|
+
if (!component.removed) {
|
|
316
|
+
if (!component.added && this.useLongestToken) {
|
|
317
|
+
let value = newTokens.slice(newPos, newPos + component.count);
|
|
318
|
+
value = value.map(function(value2, i) {
|
|
319
|
+
const oldValue = oldTokens[oldPos + i];
|
|
320
|
+
return oldValue.length > value2.length ? oldValue : value2;
|
|
321
|
+
});
|
|
322
|
+
component.value = this.join(value);
|
|
323
|
+
} else {
|
|
324
|
+
component.value = this.join(newTokens.slice(newPos, newPos + component.count));
|
|
325
|
+
}
|
|
326
|
+
newPos += component.count;
|
|
327
|
+
if (!component.added) {
|
|
328
|
+
oldPos += component.count;
|
|
329
|
+
}
|
|
330
|
+
} else {
|
|
331
|
+
component.value = this.join(oldTokens.slice(oldPos, oldPos + component.count));
|
|
332
|
+
oldPos += component.count;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return components;
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
// node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/diff/line.js
|
|
340
|
+
init_esm_shims();
|
|
341
|
+
var LineDiff = class extends Diff {
|
|
342
|
+
constructor() {
|
|
343
|
+
super(...arguments);
|
|
344
|
+
this.tokenize = tokenize;
|
|
345
|
+
}
|
|
346
|
+
equals(left, right, options) {
|
|
347
|
+
if (options.ignoreWhitespace) {
|
|
348
|
+
if (!options.newlineIsToken || !left.includes("\n")) {
|
|
349
|
+
left = left.trim();
|
|
350
|
+
}
|
|
351
|
+
if (!options.newlineIsToken || !right.includes("\n")) {
|
|
352
|
+
right = right.trim();
|
|
353
|
+
}
|
|
354
|
+
} else if (options.ignoreNewlineAtEof && !options.newlineIsToken) {
|
|
355
|
+
if (left.endsWith("\n")) {
|
|
356
|
+
left = left.slice(0, -1);
|
|
357
|
+
}
|
|
358
|
+
if (right.endsWith("\n")) {
|
|
359
|
+
right = right.slice(0, -1);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return super.equals(left, right, options);
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
var lineDiff = new LineDiff();
|
|
366
|
+
function diffLines(oldStr, newStr, options) {
|
|
367
|
+
return lineDiff.diff(oldStr, newStr, options);
|
|
368
|
+
}
|
|
369
|
+
function tokenize(value, options) {
|
|
370
|
+
if (options.stripTrailingCr) {
|
|
371
|
+
value = value.replace(/\r\n/g, "\n");
|
|
372
|
+
}
|
|
373
|
+
const retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/);
|
|
374
|
+
if (!linesAndNewlines[linesAndNewlines.length - 1]) {
|
|
375
|
+
linesAndNewlines.pop();
|
|
376
|
+
}
|
|
377
|
+
for (let i = 0; i < linesAndNewlines.length; i++) {
|
|
378
|
+
const line = linesAndNewlines[i];
|
|
379
|
+
if (i % 2 && !options.newlineIsToken) {
|
|
380
|
+
retLines[retLines.length - 1] += line;
|
|
381
|
+
} else {
|
|
382
|
+
retLines.push(line);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return retLines;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// scripts/cli.ts
|
|
389
|
+
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
390
|
+
|
|
7
391
|
// scripts/cli-generator.ts
|
|
392
|
+
init_esm_shims();
|
|
8
393
|
import fs from "fs-extra";
|
|
9
|
-
import
|
|
10
|
-
import { fileURLToPath } from "url";
|
|
394
|
+
import path2 from "path";
|
|
395
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
11
396
|
import os from "os";
|
|
12
|
-
var
|
|
13
|
-
var
|
|
397
|
+
var __filename2 = fileURLToPath2(import.meta.url);
|
|
398
|
+
var __dirname2 = path2.dirname(__filename2);
|
|
14
399
|
var VARIANTS = {
|
|
15
400
|
WITH_BEADS: "with-beads",
|
|
16
401
|
WITHOUT_BEADS: "without-beads"
|
|
@@ -50,12 +435,12 @@ var VARIANT_OPTIONS = [
|
|
|
50
435
|
}
|
|
51
436
|
];
|
|
52
437
|
function getScopeOptions(terminalWidth = 80) {
|
|
53
|
-
const projectPath =
|
|
438
|
+
const projectPath = path2.join(
|
|
54
439
|
process.cwd(),
|
|
55
440
|
DIRECTORIES.CLAUDE,
|
|
56
441
|
DIRECTORIES.COMMANDS
|
|
57
442
|
);
|
|
58
|
-
const userPath =
|
|
443
|
+
const userPath = path2.join(
|
|
59
444
|
os.homedir(),
|
|
60
445
|
DIRECTORIES.CLAUDE,
|
|
61
446
|
DIRECTORIES.COMMANDS
|
|
@@ -73,16 +458,58 @@ function getScopeOptions(terminalWidth = 80) {
|
|
|
73
458
|
}
|
|
74
459
|
];
|
|
75
460
|
}
|
|
76
|
-
async function
|
|
77
|
-
const sourcePath =
|
|
78
|
-
|
|
461
|
+
async function checkExistingFiles(outputPath, variant, scope, options) {
|
|
462
|
+
const sourcePath = path2.join(
|
|
463
|
+
__dirname2,
|
|
464
|
+
"..",
|
|
465
|
+
DIRECTORIES.DOWNLOADS,
|
|
466
|
+
variant || VARIANTS.WITH_BEADS
|
|
467
|
+
);
|
|
468
|
+
const destinationPath = outputPath || getDestinationPath(outputPath, scope);
|
|
469
|
+
if (!destinationPath) {
|
|
470
|
+
return [];
|
|
471
|
+
}
|
|
472
|
+
const files = await fs.readdir(sourcePath);
|
|
473
|
+
const existingFiles = [];
|
|
474
|
+
const prefix = options?.commandPrefix || "";
|
|
475
|
+
for (const file of files) {
|
|
476
|
+
const destFileName = prefix + file;
|
|
477
|
+
const destFilePath = path2.join(destinationPath, destFileName);
|
|
478
|
+
const sourceFilePath = path2.join(sourcePath, file);
|
|
479
|
+
if (await fs.pathExists(destFilePath)) {
|
|
480
|
+
const existingContent = await fs.readFile(destFilePath, "utf-8");
|
|
481
|
+
const newContent = await fs.readFile(sourceFilePath, "utf-8");
|
|
482
|
+
existingFiles.push({
|
|
483
|
+
filename: destFileName,
|
|
484
|
+
existingContent,
|
|
485
|
+
newContent,
|
|
486
|
+
isIdentical: existingContent === newContent
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return existingFiles;
|
|
491
|
+
}
|
|
492
|
+
var CATEGORY_ORDER = [
|
|
493
|
+
"Test-Driven Development",
|
|
494
|
+
"Planning",
|
|
495
|
+
"Workflow",
|
|
496
|
+
"Worktree Management",
|
|
497
|
+
"Utilities",
|
|
498
|
+
"Ship / Show / Ask"
|
|
499
|
+
];
|
|
500
|
+
async function loadCommandsMetadata(variant) {
|
|
501
|
+
const sourcePath = path2.join(
|
|
502
|
+
__dirname2,
|
|
79
503
|
"..",
|
|
80
504
|
DIRECTORIES.DOWNLOADS,
|
|
81
505
|
variant || VARIANTS.WITH_BEADS
|
|
82
506
|
);
|
|
83
|
-
const metadataPath =
|
|
507
|
+
const metadataPath = path2.join(sourcePath, "commands-metadata.json");
|
|
84
508
|
const metadataContent = await fs.readFile(metadataPath, "utf-8");
|
|
85
|
-
|
|
509
|
+
return JSON.parse(metadataContent);
|
|
510
|
+
}
|
|
511
|
+
async function getCommandsGroupedByCategory(variant) {
|
|
512
|
+
const metadata = await loadCommandsMetadata(variant);
|
|
86
513
|
const grouped = {};
|
|
87
514
|
for (const [filename, data] of Object.entries(metadata)) {
|
|
88
515
|
const category = data.category;
|
|
@@ -91,9 +518,16 @@ async function getCommandsGroupedByCategory(variant) {
|
|
|
91
518
|
}
|
|
92
519
|
grouped[category].push({
|
|
93
520
|
value: filename,
|
|
94
|
-
label: filename
|
|
521
|
+
label: filename,
|
|
522
|
+
hint: data.hint,
|
|
523
|
+
selectedByDefault: data.selectedByDefault !== false
|
|
95
524
|
});
|
|
96
525
|
}
|
|
526
|
+
for (const category of Object.keys(grouped)) {
|
|
527
|
+
if (!CATEGORY_ORDER.includes(category)) {
|
|
528
|
+
throw new Error(`Unknown category: ${category}`);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
97
531
|
for (const category of Object.keys(grouped)) {
|
|
98
532
|
grouped[category].sort((a, b) => {
|
|
99
533
|
const orderA = metadata[a.value].order;
|
|
@@ -101,17 +535,43 @@ async function getCommandsGroupedByCategory(variant) {
|
|
|
101
535
|
return orderA - orderB;
|
|
102
536
|
});
|
|
103
537
|
}
|
|
104
|
-
|
|
538
|
+
const sortedCategories = Object.keys(grouped).sort((a, b) => {
|
|
539
|
+
return CATEGORY_ORDER.indexOf(a) - CATEGORY_ORDER.indexOf(b);
|
|
540
|
+
});
|
|
541
|
+
const sortedGrouped = {};
|
|
542
|
+
for (const category of sortedCategories) {
|
|
543
|
+
sortedGrouped[category] = grouped[category];
|
|
544
|
+
}
|
|
545
|
+
return sortedGrouped;
|
|
546
|
+
}
|
|
547
|
+
function extractLabelFromTool(tool) {
|
|
548
|
+
const match = tool.match(/^Bash\(([^:]+):/);
|
|
549
|
+
return match ? match[1] : tool;
|
|
550
|
+
}
|
|
551
|
+
async function getRequestedToolsOptions(variant) {
|
|
552
|
+
const metadata = await loadCommandsMetadata(variant);
|
|
553
|
+
const allTools = /* @__PURE__ */ new Set();
|
|
554
|
+
for (const data of Object.values(metadata)) {
|
|
555
|
+
if (data["_requested-tools"]) {
|
|
556
|
+
for (const tool of data["_requested-tools"]) {
|
|
557
|
+
allTools.add(tool);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return Array.from(allTools).map((tool) => ({
|
|
562
|
+
value: tool,
|
|
563
|
+
label: extractLabelFromTool(tool)
|
|
564
|
+
}));
|
|
105
565
|
}
|
|
106
566
|
function getDestinationPath(outputPath, scope) {
|
|
107
567
|
if (outputPath) {
|
|
108
568
|
return outputPath;
|
|
109
569
|
}
|
|
110
570
|
if (scope === SCOPES.PROJECT) {
|
|
111
|
-
return
|
|
571
|
+
return path2.join(process.cwd(), DIRECTORIES.CLAUDE, DIRECTORIES.COMMANDS);
|
|
112
572
|
}
|
|
113
573
|
if (scope === SCOPES.USER) {
|
|
114
|
-
return
|
|
574
|
+
return path2.join(os.homedir(), DIRECTORIES.CLAUDE, DIRECTORIES.COMMANDS);
|
|
115
575
|
}
|
|
116
576
|
return void 0;
|
|
117
577
|
}
|
|
@@ -133,8 +593,8 @@ function extractTemplateBlocks(content) {
|
|
|
133
593
|
return blocks;
|
|
134
594
|
}
|
|
135
595
|
async function generateToDirectory(outputPath, variant, scope, options) {
|
|
136
|
-
const sourcePath =
|
|
137
|
-
|
|
596
|
+
const sourcePath = path2.join(
|
|
597
|
+
__dirname2,
|
|
138
598
|
"..",
|
|
139
599
|
DIRECTORIES.DOWNLOADS,
|
|
140
600
|
variant || VARIANTS.WITH_BEADS
|
|
@@ -144,22 +604,39 @@ async function generateToDirectory(outputPath, variant, scope, options) {
|
|
|
144
604
|
throw new Error("Either outputPath or scope must be provided");
|
|
145
605
|
}
|
|
146
606
|
const allFiles = await fs.readdir(sourcePath);
|
|
147
|
-
|
|
148
|
-
if (options?.
|
|
607
|
+
let files = options?.commands ? allFiles.filter((f) => options.commands.includes(f)) : allFiles;
|
|
608
|
+
if (options?.skipFiles) {
|
|
609
|
+
files = files.filter((f) => !options.skipFiles.includes(f));
|
|
610
|
+
}
|
|
611
|
+
if (options?.commands || options?.skipFiles) {
|
|
149
612
|
await fs.ensureDir(destinationPath);
|
|
150
613
|
for (const file of files) {
|
|
151
614
|
await fs.copy(
|
|
152
|
-
|
|
153
|
-
|
|
615
|
+
path2.join(sourcePath, file),
|
|
616
|
+
path2.join(destinationPath, file)
|
|
154
617
|
);
|
|
155
618
|
}
|
|
156
619
|
} else {
|
|
157
620
|
await fs.copy(sourcePath, destinationPath, {});
|
|
158
621
|
}
|
|
622
|
+
if (options?.allowedTools && options.allowedTools.length > 0) {
|
|
623
|
+
for (const file of files) {
|
|
624
|
+
const filePath = path2.join(destinationPath, file);
|
|
625
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
626
|
+
const allowedToolsYaml = `allowed-tools: ${options.allowedTools.join(", ")}`;
|
|
627
|
+
const modifiedContent = content.replace(
|
|
628
|
+
/^---\n/,
|
|
629
|
+
`---
|
|
630
|
+
${allowedToolsYaml}
|
|
631
|
+
`
|
|
632
|
+
);
|
|
633
|
+
await fs.writeFile(filePath, modifiedContent);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
159
636
|
if (options?.commandPrefix) {
|
|
160
637
|
for (const file of files) {
|
|
161
|
-
const oldPath =
|
|
162
|
-
const newPath =
|
|
638
|
+
const oldPath = path2.join(destinationPath, file);
|
|
639
|
+
const newPath = path2.join(destinationPath, options.commandPrefix + file);
|
|
163
640
|
await fs.rename(oldPath, newPath);
|
|
164
641
|
}
|
|
165
642
|
}
|
|
@@ -167,7 +644,7 @@ async function generateToDirectory(outputPath, variant, scope, options) {
|
|
|
167
644
|
if (!options?.skipTemplateInjection) {
|
|
168
645
|
let templateSourcePath = null;
|
|
169
646
|
for (const filename of TEMPLATE_SOURCE_FILES) {
|
|
170
|
-
const candidatePath =
|
|
647
|
+
const candidatePath = path2.join(process.cwd(), filename);
|
|
171
648
|
if (await fs.pathExists(candidatePath)) {
|
|
172
649
|
templateSourcePath = candidatePath;
|
|
173
650
|
break;
|
|
@@ -178,9 +655,9 @@ async function generateToDirectory(outputPath, variant, scope, options) {
|
|
|
178
655
|
const templates = extractTemplateBlocks(sourceContent);
|
|
179
656
|
if (templates.length > 0) {
|
|
180
657
|
for (const file of files) {
|
|
181
|
-
const commandName =
|
|
658
|
+
const commandName = path2.basename(file, ".md");
|
|
182
659
|
const actualFileName = options?.commandPrefix ? options.commandPrefix + file : file;
|
|
183
|
-
const filePath =
|
|
660
|
+
const filePath = path2.join(destinationPath, actualFileName);
|
|
184
661
|
let content = await fs.readFile(filePath, "utf-8");
|
|
185
662
|
let modified = false;
|
|
186
663
|
for (const template of templates) {
|
|
@@ -208,6 +685,106 @@ async function generateToDirectory(outputPath, variant, scope, options) {
|
|
|
208
685
|
}
|
|
209
686
|
|
|
210
687
|
// scripts/cli.ts
|
|
688
|
+
var pc = process.env.FORCE_COLOR ? import_picocolors.default.createColors(true) : import_picocolors.default;
|
|
689
|
+
function splitChangeIntoLines(value) {
|
|
690
|
+
const lines = value.split("\n");
|
|
691
|
+
if (lines[lines.length - 1] === "") lines.pop();
|
|
692
|
+
return lines;
|
|
693
|
+
}
|
|
694
|
+
function formatCompactDiff(oldContent, newContent, contextLines = 3) {
|
|
695
|
+
const changes = diffLines(oldContent, newContent);
|
|
696
|
+
const lines = [];
|
|
697
|
+
const allLines = [];
|
|
698
|
+
let oldLineNum = 1;
|
|
699
|
+
let newLineNum = 1;
|
|
700
|
+
for (const change of changes) {
|
|
701
|
+
const changeLines = splitChangeIntoLines(change.value);
|
|
702
|
+
for (const text2 of changeLines) {
|
|
703
|
+
if (change.added) {
|
|
704
|
+
allLines.push({
|
|
705
|
+
text: text2,
|
|
706
|
+
type: "added",
|
|
707
|
+
oldLineNum: -1,
|
|
708
|
+
newLineNum: newLineNum++
|
|
709
|
+
});
|
|
710
|
+
} else if (change.removed) {
|
|
711
|
+
allLines.push({
|
|
712
|
+
text: text2,
|
|
713
|
+
type: "removed",
|
|
714
|
+
oldLineNum: oldLineNum++,
|
|
715
|
+
newLineNum: -1
|
|
716
|
+
});
|
|
717
|
+
} else {
|
|
718
|
+
allLines.push({
|
|
719
|
+
text: text2,
|
|
720
|
+
type: "unchanged",
|
|
721
|
+
oldLineNum: oldLineNum++,
|
|
722
|
+
newLineNum: newLineNum++
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
let i = 0;
|
|
728
|
+
while (i < allLines.length) {
|
|
729
|
+
if (allLines[i].type === "unchanged") {
|
|
730
|
+
i++;
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
const hunkStart = Math.max(0, i - contextLines);
|
|
734
|
+
let hunkEnd = i;
|
|
735
|
+
while (hunkEnd < allLines.length) {
|
|
736
|
+
if (allLines[hunkEnd].type !== "unchanged") {
|
|
737
|
+
hunkEnd++;
|
|
738
|
+
} else {
|
|
739
|
+
let nextChange = hunkEnd;
|
|
740
|
+
while (nextChange < allLines.length && nextChange < hunkEnd + contextLines * 2 + 1) {
|
|
741
|
+
if (allLines[nextChange].type !== "unchanged") break;
|
|
742
|
+
nextChange++;
|
|
743
|
+
}
|
|
744
|
+
if (nextChange < allLines.length && nextChange < hunkEnd + contextLines * 2 + 1 && allLines[nextChange].type !== "unchanged") {
|
|
745
|
+
hunkEnd = nextChange + 1;
|
|
746
|
+
} else {
|
|
747
|
+
break;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
hunkEnd = Math.min(allLines.length, hunkEnd + contextLines);
|
|
752
|
+
const hunkLines = allLines.slice(hunkStart, hunkEnd);
|
|
753
|
+
const firstOldLine = hunkLines.find((l) => l.oldLineNum > 0)?.oldLineNum || 1;
|
|
754
|
+
const firstNewLine = hunkLines.find((l) => l.newLineNum > 0)?.newLineNum || 1;
|
|
755
|
+
const oldCount = hunkLines.filter((l) => l.type !== "added").length;
|
|
756
|
+
const newCount = hunkLines.filter((l) => l.type !== "removed").length;
|
|
757
|
+
lines.push(
|
|
758
|
+
pc.cyan(
|
|
759
|
+
`@@ -${firstOldLine},${oldCount} +${firstNewLine},${newCount} @@`
|
|
760
|
+
)
|
|
761
|
+
);
|
|
762
|
+
for (let j = hunkStart; j < hunkEnd; j++) {
|
|
763
|
+
const line = allLines[j];
|
|
764
|
+
if (line.type === "added") {
|
|
765
|
+
lines.push(pc.bgGreen(pc.black(`+ ${line.text}`)));
|
|
766
|
+
} else if (line.type === "removed") {
|
|
767
|
+
lines.push(pc.bgRed(pc.black(`- ${line.text}`)));
|
|
768
|
+
} else {
|
|
769
|
+
lines.push(pc.dim(` ${line.text}`));
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
lines.push("");
|
|
773
|
+
i = hunkEnd;
|
|
774
|
+
}
|
|
775
|
+
return lines.join("\n").trimEnd();
|
|
776
|
+
}
|
|
777
|
+
function getDiffStats(oldContent, newContent) {
|
|
778
|
+
const changes = diffLines(oldContent, newContent);
|
|
779
|
+
let added = 0;
|
|
780
|
+
let removed = 0;
|
|
781
|
+
for (const change of changes) {
|
|
782
|
+
const lineCount = splitChangeIntoLines(change.value).length;
|
|
783
|
+
if (change.added) added += lineCount;
|
|
784
|
+
else if (change.removed) removed += lineCount;
|
|
785
|
+
}
|
|
786
|
+
return { added, removed };
|
|
787
|
+
}
|
|
211
788
|
var BATMAN_LOGO = `
|
|
212
789
|
_==/ i i \\==_
|
|
213
790
|
/XX/ |\\___/| \\XX\\
|
|
@@ -230,11 +807,26 @@ async function main(args) {
|
|
|
230
807
|
let scope;
|
|
231
808
|
let commandPrefix;
|
|
232
809
|
let selectedCommands;
|
|
810
|
+
let selectedAllowedTools;
|
|
811
|
+
let cachedExistingFiles;
|
|
233
812
|
if (args?.variant && args?.scope && args?.prefix !== void 0) {
|
|
234
813
|
variant = args.variant;
|
|
235
814
|
scope = args.scope;
|
|
236
815
|
commandPrefix = args.prefix;
|
|
237
816
|
selectedCommands = args.commands;
|
|
817
|
+
if (args.updateExisting) {
|
|
818
|
+
cachedExistingFiles = await checkExistingFiles(
|
|
819
|
+
void 0,
|
|
820
|
+
variant,
|
|
821
|
+
scope,
|
|
822
|
+
{ commandPrefix: commandPrefix || "" }
|
|
823
|
+
);
|
|
824
|
+
selectedCommands = cachedExistingFiles.map((f) => f.filename);
|
|
825
|
+
if (selectedCommands.length === 0) {
|
|
826
|
+
log.warn("No existing commands found in target directory");
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
238
830
|
} else {
|
|
239
831
|
variant = await select({
|
|
240
832
|
message: "Select variant",
|
|
@@ -259,56 +851,213 @@ async function main(args) {
|
|
|
259
851
|
if (isCancel(commandPrefix)) {
|
|
260
852
|
return;
|
|
261
853
|
}
|
|
262
|
-
|
|
263
|
-
|
|
854
|
+
let groupedCommands = await getCommandsGroupedByCategory(
|
|
855
|
+
variant
|
|
856
|
+
);
|
|
857
|
+
if (args?.updateExisting) {
|
|
858
|
+
cachedExistingFiles = await checkExistingFiles(
|
|
859
|
+
void 0,
|
|
860
|
+
variant,
|
|
861
|
+
scope,
|
|
862
|
+
{ commandPrefix: commandPrefix || "" }
|
|
863
|
+
);
|
|
864
|
+
const existingFilenames = new Set(
|
|
865
|
+
cachedExistingFiles.map((f) => f.filename)
|
|
866
|
+
);
|
|
867
|
+
const filteredGrouped = {};
|
|
868
|
+
for (const [category, commands] of Object.entries(groupedCommands)) {
|
|
869
|
+
const filtered = commands.filter(
|
|
870
|
+
(cmd) => existingFilenames.has(cmd.value)
|
|
871
|
+
);
|
|
872
|
+
if (filtered.length > 0) {
|
|
873
|
+
filteredGrouped[category] = filtered;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
groupedCommands = filteredGrouped;
|
|
877
|
+
if (Object.keys(groupedCommands).length === 0) {
|
|
878
|
+
log.warn("No existing commands found in target directory");
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
const enabledCommandValues = Object.values(groupedCommands).flat().filter((cmd) => cmd.selectedByDefault).map((cmd) => cmd.value);
|
|
264
883
|
selectedCommands = await groupMultiselect({
|
|
265
884
|
message: "Select commands to install (Enter to accept all)",
|
|
266
885
|
options: groupedCommands,
|
|
267
|
-
initialValues:
|
|
886
|
+
initialValues: enabledCommandValues
|
|
268
887
|
});
|
|
269
888
|
if (isCancel(selectedCommands)) {
|
|
270
889
|
return;
|
|
271
890
|
}
|
|
891
|
+
const requestedToolsOptions = await getRequestedToolsOptions(
|
|
892
|
+
variant
|
|
893
|
+
);
|
|
894
|
+
if (requestedToolsOptions.length > 0) {
|
|
895
|
+
selectedAllowedTools = await multiselect({
|
|
896
|
+
message: "Select allowed tools for commands (optional)",
|
|
897
|
+
options: requestedToolsOptions
|
|
898
|
+
});
|
|
899
|
+
if (isCancel(selectedAllowedTools)) {
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
const existingFiles = cachedExistingFiles ?? await checkExistingFiles(void 0, variant, scope, {
|
|
905
|
+
commandPrefix,
|
|
906
|
+
commands: selectedCommands
|
|
907
|
+
});
|
|
908
|
+
const skipFiles = [];
|
|
909
|
+
if (!args?.overwrite && !args?.skipOnConflict) {
|
|
910
|
+
for (const file of existingFiles) {
|
|
911
|
+
if (file.isIdentical) {
|
|
912
|
+
log.info(`${file.filename} is identical, skipping`);
|
|
913
|
+
skipFiles.push(file.filename);
|
|
914
|
+
continue;
|
|
915
|
+
}
|
|
916
|
+
const stats = getDiffStats(file.existingContent, file.newContent);
|
|
917
|
+
const diff = formatCompactDiff(file.existingContent, file.newContent);
|
|
918
|
+
note(diff, `Diff: ${file.filename}`);
|
|
919
|
+
log.info(`+${stats.added} -${stats.removed}`);
|
|
920
|
+
const shouldOverwrite = await confirm({
|
|
921
|
+
message: `Overwrite ${file.filename}?`
|
|
922
|
+
});
|
|
923
|
+
if (!shouldOverwrite) {
|
|
924
|
+
skipFiles.push(file.filename);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
} else if (args?.skipOnConflict) {
|
|
928
|
+
for (const file of existingFiles) {
|
|
929
|
+
if (!file.isIdentical) {
|
|
930
|
+
skipFiles.push(file.filename);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
272
933
|
}
|
|
273
|
-
const result = await generateToDirectory(
|
|
934
|
+
const result = await generateToDirectory(
|
|
935
|
+
void 0,
|
|
936
|
+
variant,
|
|
937
|
+
scope,
|
|
938
|
+
{
|
|
939
|
+
commandPrefix,
|
|
940
|
+
skipTemplateInjection: args?.skipTemplateInjection,
|
|
941
|
+
commands: selectedCommands,
|
|
942
|
+
skipFiles,
|
|
943
|
+
allowedTools: selectedAllowedTools
|
|
944
|
+
}
|
|
945
|
+
);
|
|
274
946
|
const fullPath = scope === "project" ? `${process.cwd()}/.claude/commands` : `${os2.homedir()}/.claude/commands`;
|
|
275
|
-
outro(
|
|
947
|
+
outro(
|
|
948
|
+
`Installed ${result.filesGenerated} commands to ${fullPath}
|
|
276
949
|
|
|
277
950
|
If Claude Code is already running, restart it to pick up the new commands.
|
|
278
951
|
|
|
279
|
-
Happy TDD'ing!`
|
|
952
|
+
Happy TDD'ing!`
|
|
953
|
+
);
|
|
280
954
|
}
|
|
281
955
|
|
|
282
|
-
// scripts/
|
|
283
|
-
|
|
284
|
-
var
|
|
285
|
-
|
|
286
|
-
|
|
956
|
+
// scripts/cli-options.ts
|
|
957
|
+
init_esm_shims();
|
|
958
|
+
var CLI_OPTIONS = [
|
|
959
|
+
{
|
|
960
|
+
flag: "--variant",
|
|
961
|
+
key: "variant",
|
|
962
|
+
type: "string",
|
|
963
|
+
description: "Command variant (with-beads, without-beads)",
|
|
964
|
+
example: "--variant=with-beads"
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
flag: "--scope",
|
|
968
|
+
key: "scope",
|
|
969
|
+
type: "string",
|
|
970
|
+
description: "Installation scope (project, user)",
|
|
971
|
+
example: "--scope=project"
|
|
972
|
+
},
|
|
973
|
+
{
|
|
974
|
+
flag: "--prefix",
|
|
975
|
+
key: "prefix",
|
|
976
|
+
type: "string",
|
|
977
|
+
description: "Add prefix to command names",
|
|
978
|
+
example: "--prefix=my-"
|
|
979
|
+
},
|
|
980
|
+
{
|
|
981
|
+
flag: "--commands",
|
|
982
|
+
key: "commands",
|
|
983
|
+
type: "array",
|
|
984
|
+
description: "Install only specific commands",
|
|
985
|
+
example: "--commands=commit,red,green"
|
|
986
|
+
},
|
|
987
|
+
{
|
|
988
|
+
flag: "--skip-template-injection",
|
|
989
|
+
key: "skipTemplateInjection",
|
|
990
|
+
type: "boolean",
|
|
991
|
+
description: "Skip injecting project CLAUDE.md customizations"
|
|
992
|
+
},
|
|
993
|
+
{
|
|
994
|
+
flag: "--update-existing",
|
|
995
|
+
key: "updateExisting",
|
|
996
|
+
type: "boolean",
|
|
997
|
+
description: "Only update already-installed commands"
|
|
998
|
+
},
|
|
999
|
+
{
|
|
1000
|
+
flag: "--overwrite",
|
|
1001
|
+
key: "overwrite",
|
|
1002
|
+
type: "boolean",
|
|
1003
|
+
description: "Overwrite conflicting files without prompting"
|
|
1004
|
+
},
|
|
1005
|
+
{
|
|
1006
|
+
flag: "--skip-on-conflict",
|
|
1007
|
+
key: "skipOnConflict",
|
|
1008
|
+
type: "boolean",
|
|
1009
|
+
description: "Skip conflicting files without prompting"
|
|
1010
|
+
}
|
|
287
1011
|
];
|
|
1012
|
+
function generateHelpText() {
|
|
1013
|
+
const lines = [
|
|
1014
|
+
"Usage: npx @wbern/claude-instructions [options]",
|
|
1015
|
+
"",
|
|
1016
|
+
"Options:"
|
|
1017
|
+
];
|
|
1018
|
+
for (const opt of CLI_OPTIONS) {
|
|
1019
|
+
const suffix = opt.type === "string" ? "=<value>" : opt.type === "array" ? "=<list>" : "";
|
|
1020
|
+
const padding = 28 - (opt.flag.length + suffix.length);
|
|
1021
|
+
lines.push(
|
|
1022
|
+
` ${opt.flag}${suffix}${" ".repeat(Math.max(1, padding))}${opt.description}`
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
1025
|
+
lines.push(" --help, -h Show this help message");
|
|
1026
|
+
return lines.join("\n");
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
// scripts/bin.ts
|
|
288
1030
|
function parseArgs(argv) {
|
|
289
1031
|
const args = {};
|
|
1032
|
+
const booleanOpts = CLI_OPTIONS.filter((o) => o.type === "boolean");
|
|
1033
|
+
const stringOpts = CLI_OPTIONS.filter((o) => o.type === "string");
|
|
1034
|
+
const arrayOpts = CLI_OPTIONS.filter((o) => o.type === "array");
|
|
290
1035
|
for (const arg of argv) {
|
|
291
|
-
for (const
|
|
292
|
-
if (arg === flag) {
|
|
293
|
-
args[key] = true;
|
|
1036
|
+
for (const opt of booleanOpts) {
|
|
1037
|
+
if (arg === opt.flag) {
|
|
1038
|
+
args[opt.key] = true;
|
|
294
1039
|
}
|
|
295
1040
|
}
|
|
296
|
-
for (const
|
|
297
|
-
const prefix =
|
|
1041
|
+
for (const opt of stringOpts) {
|
|
1042
|
+
const prefix = `${opt.flag}=`;
|
|
298
1043
|
if (arg.startsWith(prefix)) {
|
|
299
|
-
args[key] = arg.slice(prefix.length);
|
|
1044
|
+
args[opt.key] = arg.slice(prefix.length);
|
|
300
1045
|
}
|
|
301
1046
|
}
|
|
302
|
-
for (const
|
|
303
|
-
const prefix =
|
|
1047
|
+
for (const opt of arrayOpts) {
|
|
1048
|
+
const prefix = `${opt.flag}=`;
|
|
304
1049
|
if (arg.startsWith(prefix)) {
|
|
305
|
-
args[key] = arg.slice(prefix.length).split(",");
|
|
1050
|
+
args[opt.key] = arg.slice(prefix.length).split(",");
|
|
306
1051
|
}
|
|
307
1052
|
}
|
|
308
1053
|
}
|
|
309
1054
|
return args;
|
|
310
1055
|
}
|
|
311
1056
|
async function run(argv) {
|
|
1057
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
1058
|
+
console.log(generateHelpText());
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
312
1061
|
const args = parseArgs(argv);
|
|
313
1062
|
await main(args);
|
|
314
1063
|
}
|