@wbern/claude-instructions 1.21.0 → 2.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/README.md +4 -2
- package/bin/cli.js +414 -229
- package/package.json +8 -6
- package/src/README.md +279 -0
- package/src/fragments/aaa-pattern.md +7 -0
- package/src/fragments/beads-awareness.md +1 -0
- package/src/fragments/beads-integration.md +8 -0
- package/{downloads/without-beads/commit.md → src/fragments/commit-process.md} +0 -17
- package/src/fragments/consistency-check.md +1 -0
- package/src/fragments/discovery-phase.md +22 -0
- package/src/fragments/fallback-arguments-beads.md +3 -0
- package/src/fragments/fallback-arguments.md +1 -0
- package/src/fragments/fullwidth-dollar-note.md +1 -0
- package/src/fragments/gap-beads.md +1 -0
- package/src/fragments/git-host-detection.md +19 -0
- package/src/fragments/github-issue-fetch.md +10 -0
- package/src/fragments/no-plan-files.md +3 -0
- package/src/fragments/peeping-tom-warning.md +9 -0
- package/src/fragments/plan-beads-context-hint.md +1 -0
- package/src/fragments/plan-beads-details.md +49 -0
- package/src/fragments/plan-beads-integration.md +2 -0
- package/src/fragments/summarize-beads.md +8 -0
- package/{downloads/without-beads/summarize.md → src/fragments/summarize-structure.md} +0 -20
- package/{downloads/without-beads/tdd.md → src/fragments/tdd-fundamentals.md} +0 -21
- package/src/fragments/test-quality-criteria.md +24 -0
- package/src/fragments/universal-guidelines.md +6 -0
- package/{downloads/without-beads → src/sources}/add-command.md +11 -25
- package/{downloads/without-beads → src/sources}/ask.md +11 -6
- package/{downloads/without-beads → src/sources}/beepboop.md +7 -6
- package/{downloads/without-beads → src/sources}/busycommit.md +9 -36
- package/{downloads/without-beads → src/sources}/code-review.md +16 -30
- package/src/sources/commit.md +23 -0
- package/src/sources/cycle.md +23 -0
- package/{downloads/without-beads → src/sources}/gap.md +11 -8
- package/src/sources/green.md +23 -0
- package/src/sources/issue.md +42 -0
- package/{downloads/without-beads → src/sources}/kata.md +10 -9
- package/{downloads/without-beads → src/sources}/plan.md +18 -39
- package/{downloads/without-beads → src/sources}/pr.md +10 -6
- package/src/sources/red.md +26 -0
- package/src/sources/refactor.md +27 -0
- package/{downloads/without-beads → src/sources}/ship.md +11 -6
- package/{downloads/without-beads → src/sources}/show.md +11 -6
- package/src/sources/spike.md +23 -0
- package/src/sources/summarize.md +23 -0
- package/{downloads/without-beads → src/sources}/tdd-review.md +11 -31
- package/src/sources/tdd.md +24 -0
- package/{downloads/without-beads → src/sources}/worktree-add.md +13 -31
- package/{downloads/without-beads → src/sources}/worktree-cleanup.md +9 -27
- package/downloads/with-beads/add-command.md +0 -159
- package/downloads/with-beads/ask.md +0 -144
- package/downloads/with-beads/beepboop.md +0 -47
- package/downloads/with-beads/busycommit.md +0 -78
- package/downloads/with-beads/code-review.md +0 -263
- package/downloads/with-beads/commands-metadata.json +0 -155
- package/downloads/with-beads/commit.md +0 -49
- package/downloads/with-beads/cycle.md +0 -95
- package/downloads/with-beads/gap.md +0 -38
- package/downloads/with-beads/green.md +0 -95
- package/downloads/with-beads/issue.md +0 -152
- package/downloads/with-beads/kata.md +0 -444
- package/downloads/with-beads/plan.md +0 -186
- package/downloads/with-beads/pr.md +0 -82
- package/downloads/with-beads/red.md +0 -103
- package/downloads/with-beads/refactor.md +0 -105
- package/downloads/with-beads/ship.md +0 -98
- package/downloads/with-beads/show.md +0 -114
- package/downloads/with-beads/spike.md +0 -95
- package/downloads/with-beads/summarize.md +0 -54
- package/downloads/with-beads/tdd-review.md +0 -102
- package/downloads/with-beads/tdd.md +0 -94
- package/downloads/with-beads/worktree-add.md +0 -357
- package/downloads/with-beads/worktree-cleanup.md +0 -250
- package/downloads/without-beads/commands-metadata.json +0 -155
- package/downloads/without-beads/cycle.md +0 -90
- package/downloads/without-beads/green.md +0 -90
- package/downloads/without-beads/issue.md +0 -140
- package/downloads/without-beads/red.md +0 -98
- package/downloads/without-beads/refactor.md +0 -100
- package/downloads/without-beads/spike.md +0 -90
package/bin/cli.js
CHANGED
|
@@ -47,17 +47,17 @@ var require_picocolors = __commonJS({
|
|
|
47
47
|
var env = p.env || {};
|
|
48
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
49
|
var formatter = (open, close, replace = open) => (input) => {
|
|
50
|
-
let
|
|
51
|
-
return ~index ? open + replaceClose(
|
|
50
|
+
let string2 = "" + input, index = string2.indexOf(close, open.length);
|
|
51
|
+
return ~index ? open + replaceClose(string2, close, replace, index) + close : open + string2 + close;
|
|
52
52
|
};
|
|
53
|
-
var replaceClose = (
|
|
53
|
+
var replaceClose = (string2, close, replace, index) => {
|
|
54
54
|
let result = "", cursor = 0;
|
|
55
55
|
do {
|
|
56
|
-
result +=
|
|
56
|
+
result += string2.substring(cursor, index) + replace;
|
|
57
57
|
cursor = index + close.length;
|
|
58
|
-
index =
|
|
58
|
+
index = string2.indexOf(close, cursor);
|
|
59
59
|
} while (~index);
|
|
60
|
-
return result +
|
|
60
|
+
return result + string2.substring(cursor);
|
|
61
61
|
};
|
|
62
62
|
var createColors = (enabled = isColorSupported) => {
|
|
63
63
|
let f = enabled ? formatter : () => String;
|
|
@@ -234,16 +234,16 @@ var Diff = class {
|
|
|
234
234
|
}
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
|
-
addToPath(
|
|
238
|
-
const last =
|
|
237
|
+
addToPath(path5, added, removed, oldPosInc, options) {
|
|
238
|
+
const last = path5.lastComponent;
|
|
239
239
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
240
240
|
return {
|
|
241
|
-
oldPos:
|
|
241
|
+
oldPos: path5.oldPos + oldPosInc,
|
|
242
242
|
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
243
243
|
};
|
|
244
244
|
} else {
|
|
245
245
|
return {
|
|
246
|
-
oldPos:
|
|
246
|
+
oldPos: path5.oldPos + oldPosInc,
|
|
247
247
|
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
248
248
|
};
|
|
249
249
|
}
|
|
@@ -272,11 +272,11 @@ var Diff = class {
|
|
|
272
272
|
return left === right || !!options.ignoreCase && left.toLowerCase() === right.toLowerCase();
|
|
273
273
|
}
|
|
274
274
|
}
|
|
275
|
-
removeEmpty(
|
|
275
|
+
removeEmpty(array2) {
|
|
276
276
|
const ret = [];
|
|
277
|
-
for (let i = 0; i <
|
|
278
|
-
if (
|
|
279
|
-
ret.push(
|
|
277
|
+
for (let i = 0; i < array2.length; i++) {
|
|
278
|
+
if (array2[i]) {
|
|
279
|
+
ret.push(array2[i]);
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
return ret;
|
|
@@ -387,19 +387,255 @@ function tokenize(value, options) {
|
|
|
387
387
|
|
|
388
388
|
// scripts/cli.ts
|
|
389
389
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
390
|
+
import * as v2 from "valibot";
|
|
390
391
|
|
|
391
392
|
// scripts/cli-generator.ts
|
|
392
393
|
init_esm_shims();
|
|
393
|
-
import
|
|
394
|
+
import fs4 from "fs-extra";
|
|
395
|
+
import path4 from "path";
|
|
396
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
397
|
+
import os from "os";
|
|
398
|
+
|
|
399
|
+
// scripts/fragment-expander.ts
|
|
400
|
+
init_esm_shims();
|
|
401
|
+
import fs2 from "fs-extra";
|
|
394
402
|
import path2 from "path";
|
|
403
|
+
|
|
404
|
+
// scripts/utils.ts
|
|
405
|
+
init_esm_shims();
|
|
406
|
+
import fs from "fs";
|
|
407
|
+
function getMarkdownFiles(dir) {
|
|
408
|
+
return fs.readdirSync(dir).filter((f) => f.endsWith(".md"));
|
|
409
|
+
}
|
|
410
|
+
function getErrorMessage(err) {
|
|
411
|
+
return err instanceof Error ? err.message : String(err);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// scripts/fragment-expander.ts
|
|
415
|
+
var TRANSFORM_BLOCK_REGEX = /<!--\s*docs\s+(\w+)([^>]*)-->([\s\S]*?)<!--\s*\/docs\s*-->/g;
|
|
416
|
+
function parseOptions(attrString) {
|
|
417
|
+
const options = {};
|
|
418
|
+
const attrRegex = /(\w+)=['"]([^'"]*)['"]/g;
|
|
419
|
+
let match;
|
|
420
|
+
while ((match = attrRegex.exec(attrString)) !== null) {
|
|
421
|
+
options[match[1]] = match[2];
|
|
422
|
+
}
|
|
423
|
+
return options;
|
|
424
|
+
}
|
|
425
|
+
function expandContent(content, options) {
|
|
426
|
+
const { baseDir, flags } = options;
|
|
427
|
+
return content.replace(
|
|
428
|
+
TRANSFORM_BLOCK_REGEX,
|
|
429
|
+
(_match, transformName, attrString) => {
|
|
430
|
+
if (transformName !== "INCLUDE") {
|
|
431
|
+
throw new Error(`Unknown transform type: ${transformName}`);
|
|
432
|
+
}
|
|
433
|
+
const attrs = parseOptions(attrString);
|
|
434
|
+
const { path: includePath, featureFlag, elsePath } = attrs;
|
|
435
|
+
if (featureFlag && !flags.includes(featureFlag)) {
|
|
436
|
+
if (elsePath) {
|
|
437
|
+
const fullElsePath = path2.join(baseDir, elsePath);
|
|
438
|
+
try {
|
|
439
|
+
return fs2.readFileSync(fullElsePath, "utf8");
|
|
440
|
+
} catch (err) {
|
|
441
|
+
throw new Error(
|
|
442
|
+
`Failed to read elsePath '${elsePath}': ${getErrorMessage(err)}`
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return "";
|
|
447
|
+
}
|
|
448
|
+
if (!includePath) {
|
|
449
|
+
throw new Error("INCLUDE directive missing required 'path' attribute");
|
|
450
|
+
}
|
|
451
|
+
const fullPath = path2.join(baseDir, includePath);
|
|
452
|
+
try {
|
|
453
|
+
return fs2.readFileSync(fullPath, "utf8");
|
|
454
|
+
} catch (err) {
|
|
455
|
+
throw new Error(
|
|
456
|
+
`Failed to read '${includePath}': ${getErrorMessage(err)}`
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// scripts/generate-readme.ts
|
|
464
|
+
init_esm_shims();
|
|
465
|
+
import fs3 from "fs";
|
|
466
|
+
import path3 from "path";
|
|
395
467
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
396
|
-
import
|
|
468
|
+
import * as v from "valibot";
|
|
469
|
+
|
|
470
|
+
// scripts/cli-options.ts
|
|
471
|
+
init_esm_shims();
|
|
472
|
+
var CLI_OPTIONS = [
|
|
473
|
+
{
|
|
474
|
+
flag: "--scope",
|
|
475
|
+
key: "scope",
|
|
476
|
+
type: "string",
|
|
477
|
+
description: "Installation scope (project, user)",
|
|
478
|
+
example: "--scope=project",
|
|
479
|
+
requiredForNonInteractive: true
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
flag: "--prefix",
|
|
483
|
+
key: "prefix",
|
|
484
|
+
type: "string",
|
|
485
|
+
description: "Add prefix to command names",
|
|
486
|
+
example: "--prefix=my-"
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
flag: "--commands",
|
|
490
|
+
key: "commands",
|
|
491
|
+
type: "array",
|
|
492
|
+
description: "Install only specific commands",
|
|
493
|
+
example: "--commands=commit,red,green"
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
flag: "--skip-template-injection",
|
|
497
|
+
key: "skipTemplateInjection",
|
|
498
|
+
type: "boolean",
|
|
499
|
+
description: "Skip injecting project CLAUDE.md customizations"
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
flag: "--update-existing",
|
|
503
|
+
key: "updateExisting",
|
|
504
|
+
type: "boolean",
|
|
505
|
+
description: "Only update already-installed commands"
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
flag: "--overwrite",
|
|
509
|
+
key: "overwrite",
|
|
510
|
+
type: "boolean",
|
|
511
|
+
description: "Overwrite conflicting files without prompting"
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
flag: "--skip-on-conflict",
|
|
515
|
+
key: "skipOnConflict",
|
|
516
|
+
type: "boolean",
|
|
517
|
+
description: "Skip conflicting files without prompting"
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
flag: "--flags",
|
|
521
|
+
key: "flags",
|
|
522
|
+
type: "array",
|
|
523
|
+
description: "Enable feature flags (beads, github, gitlab, etc.)",
|
|
524
|
+
example: "--flags=beads,github"
|
|
525
|
+
}
|
|
526
|
+
];
|
|
527
|
+
function generateHelpText() {
|
|
528
|
+
const lines = [
|
|
529
|
+
"Usage: npx @wbern/claude-instructions [options]",
|
|
530
|
+
"",
|
|
531
|
+
"Options:"
|
|
532
|
+
];
|
|
533
|
+
for (const opt of CLI_OPTIONS) {
|
|
534
|
+
const suffix = opt.type === "string" ? "=<value>" : opt.type === "array" ? "=<list>" : "";
|
|
535
|
+
const padding = 28 - (opt.flag.length + suffix.length);
|
|
536
|
+
lines.push(
|
|
537
|
+
` ${opt.flag}${suffix}${" ".repeat(Math.max(1, padding))}${opt.description}`
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
lines.push(" --help, -h Show this help message");
|
|
541
|
+
lines.push(" --version, -v Show version number");
|
|
542
|
+
return lines.join("\n");
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// scripts/generate-readme.ts
|
|
397
546
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
398
|
-
var __dirname2 =
|
|
399
|
-
var
|
|
400
|
-
|
|
401
|
-
|
|
547
|
+
var __dirname2 = path3.dirname(__filename2);
|
|
548
|
+
var PROJECT_ROOT = path3.resolve(__dirname2, "..");
|
|
549
|
+
var SOURCES_DIR = "src/sources";
|
|
550
|
+
var FRONTMATTER_REGEX = /^---\s*\n([\s\S]*?)\n---/;
|
|
551
|
+
var CATEGORIES = {
|
|
552
|
+
PLANNING: "Planning",
|
|
553
|
+
TDD: "Test-Driven Development",
|
|
554
|
+
WORKFLOW: "Workflow",
|
|
555
|
+
SHIP_SHOW_ASK: "Ship / Show / Ask",
|
|
556
|
+
WORKTREE: "Worktree Management",
|
|
557
|
+
UTILITIES: "Utilities"
|
|
402
558
|
};
|
|
559
|
+
var CategoryValues = Object.values(CATEGORIES);
|
|
560
|
+
var CategorySchema = v.picklist(CategoryValues);
|
|
561
|
+
var RequiredFrontmatterSchema = v.object({
|
|
562
|
+
description: v.pipe(v.string(), v.minLength(1)),
|
|
563
|
+
_order: v.number()
|
|
564
|
+
});
|
|
565
|
+
var IncludeOptionsSchema = v.object({
|
|
566
|
+
path: v.string()
|
|
567
|
+
});
|
|
568
|
+
function parseFrontmatter(content) {
|
|
569
|
+
const match = content.match(FRONTMATTER_REGEX);
|
|
570
|
+
if (!match) return {};
|
|
571
|
+
const frontmatter = {};
|
|
572
|
+
const lines = match[1].split("\n");
|
|
573
|
+
let currentKey = null;
|
|
574
|
+
let currentArray = null;
|
|
575
|
+
for (const line of lines) {
|
|
576
|
+
if (line.match(/^\s+-\s+/) && currentKey && currentArray) {
|
|
577
|
+
const value2 = line.replace(/^\s+-\s+/, "").trim();
|
|
578
|
+
currentArray.push(value2);
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
581
|
+
if (currentKey && currentArray) {
|
|
582
|
+
frontmatter[currentKey] = currentArray;
|
|
583
|
+
currentKey = null;
|
|
584
|
+
currentArray = null;
|
|
585
|
+
}
|
|
586
|
+
const colonIndex = line.indexOf(":");
|
|
587
|
+
if (colonIndex === -1) continue;
|
|
588
|
+
const key = line.slice(0, colonIndex).trim();
|
|
589
|
+
let value = line.slice(colonIndex + 1).trim();
|
|
590
|
+
if (value === "") {
|
|
591
|
+
currentKey = key;
|
|
592
|
+
currentArray = [];
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
if (key === "_order" && !isNaN(Number(value))) {
|
|
596
|
+
value = parseInt(value, 10);
|
|
597
|
+
}
|
|
598
|
+
if (key === "_selectedByDefault") {
|
|
599
|
+
frontmatter[key] = value === "true";
|
|
600
|
+
continue;
|
|
601
|
+
}
|
|
602
|
+
frontmatter[key] = value;
|
|
603
|
+
}
|
|
604
|
+
if (currentKey && currentArray) {
|
|
605
|
+
frontmatter[currentKey] = currentArray;
|
|
606
|
+
}
|
|
607
|
+
return frontmatter;
|
|
608
|
+
}
|
|
609
|
+
function getCategory(frontmatter) {
|
|
610
|
+
const category = frontmatter._category || CATEGORIES.UTILITIES;
|
|
611
|
+
return v.parse(CategorySchema, category);
|
|
612
|
+
}
|
|
613
|
+
function generateCommandsMetadata() {
|
|
614
|
+
const sourcesDir = path3.join(PROJECT_ROOT, SOURCES_DIR);
|
|
615
|
+
const files = getMarkdownFiles(sourcesDir);
|
|
616
|
+
const metadata = {};
|
|
617
|
+
for (const file of files) {
|
|
618
|
+
const content = fs3.readFileSync(path3.join(sourcesDir, file), "utf8");
|
|
619
|
+
const frontmatter = parseFrontmatter(content);
|
|
620
|
+
const validated = v.parse(RequiredFrontmatterSchema, frontmatter);
|
|
621
|
+
const requestedTools = frontmatter[REQUESTED_TOOLS_KEY];
|
|
622
|
+
metadata[file] = {
|
|
623
|
+
description: validated.description,
|
|
624
|
+
hint: frontmatter._hint,
|
|
625
|
+
category: getCategory(frontmatter),
|
|
626
|
+
order: validated._order,
|
|
627
|
+
...frontmatter._selectedByDefault === false ? { selectedByDefault: false } : {},
|
|
628
|
+
...requestedTools ? { [REQUESTED_TOOLS_KEY]: requestedTools } : {}
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
return metadata;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// scripts/cli-generator.ts
|
|
635
|
+
import { lint } from "markdownlint/sync";
|
|
636
|
+
import { applyFixes } from "markdownlint";
|
|
637
|
+
var __filename3 = fileURLToPath3(import.meta.url);
|
|
638
|
+
var __dirname3 = path4.dirname(__filename3);
|
|
403
639
|
var SCOPES = {
|
|
404
640
|
PROJECT: "project",
|
|
405
641
|
USER: "user"
|
|
@@ -407,7 +643,7 @@ var SCOPES = {
|
|
|
407
643
|
var DIRECTORIES = {
|
|
408
644
|
CLAUDE: ".claude",
|
|
409
645
|
COMMANDS: "commands",
|
|
410
|
-
|
|
646
|
+
SOURCES: "src/sources"
|
|
411
647
|
};
|
|
412
648
|
var TEMPLATE_SOURCE_FILES = ["CLAUDE.md", "AGENTS.md"];
|
|
413
649
|
var REQUESTED_TOOLS_KEY = "_requested-tools";
|
|
@@ -423,25 +659,27 @@ function truncatePathFromLeft(pathStr, maxLength) {
|
|
|
423
659
|
}
|
|
424
660
|
return ELLIPSIS + truncated;
|
|
425
661
|
}
|
|
426
|
-
var
|
|
662
|
+
var FLAG_OPTIONS = [
|
|
427
663
|
{
|
|
428
|
-
value:
|
|
429
|
-
label: "
|
|
430
|
-
hint: "
|
|
664
|
+
value: "beads",
|
|
665
|
+
label: "Beads MCP",
|
|
666
|
+
hint: "Local issue tracking",
|
|
667
|
+
category: "Feature Flags"
|
|
431
668
|
},
|
|
432
669
|
{
|
|
433
|
-
value:
|
|
434
|
-
label: "
|
|
435
|
-
hint: "
|
|
670
|
+
value: "no-plan-files",
|
|
671
|
+
label: "No Plan Files",
|
|
672
|
+
hint: "Forbid Claude Code's internal plan.md",
|
|
673
|
+
category: "Feature Flags"
|
|
436
674
|
}
|
|
437
675
|
];
|
|
438
676
|
function getScopeOptions(terminalWidth = 80) {
|
|
439
|
-
const projectPath =
|
|
677
|
+
const projectPath = path4.join(
|
|
440
678
|
process.cwd(),
|
|
441
679
|
DIRECTORIES.CLAUDE,
|
|
442
680
|
DIRECTORIES.COMMANDS
|
|
443
681
|
);
|
|
444
|
-
const userPath =
|
|
682
|
+
const userPath = path4.join(
|
|
445
683
|
os.homedir(),
|
|
446
684
|
DIRECTORIES.CLAUDE,
|
|
447
685
|
DIRECTORIES.COMMANDS
|
|
@@ -459,31 +697,36 @@ function getScopeOptions(terminalWidth = 80) {
|
|
|
459
697
|
}
|
|
460
698
|
];
|
|
461
699
|
}
|
|
462
|
-
async function checkExistingFiles(outputPath,
|
|
463
|
-
const sourcePath =
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
variant || VARIANTS.WITH_BEADS
|
|
468
|
-
);
|
|
469
|
-
const destinationPath = outputPath || getDestinationPath(outputPath, scope);
|
|
470
|
-
const allFiles = await fs.readdir(sourcePath);
|
|
700
|
+
async function checkExistingFiles(outputPath, scope, options) {
|
|
701
|
+
const sourcePath = path4.join(__dirname3, "..", DIRECTORIES.SOURCES);
|
|
702
|
+
const destinationPath = getDestinationPath(outputPath, scope);
|
|
703
|
+
const flags = options?.flags ?? [];
|
|
704
|
+
const allFiles = await fs4.readdir(sourcePath);
|
|
471
705
|
const files = options?.commands ? allFiles.filter((f) => options.commands.includes(f)) : allFiles;
|
|
472
706
|
const existingFiles = [];
|
|
473
707
|
const prefix = options?.commandPrefix || "";
|
|
474
708
|
let metadata = null;
|
|
475
709
|
let allowedToolsSet = null;
|
|
476
710
|
if (options?.allowedTools && options.allowedTools.length > 0) {
|
|
477
|
-
metadata = await loadCommandsMetadata(
|
|
711
|
+
metadata = await loadCommandsMetadata();
|
|
478
712
|
allowedToolsSet = new Set(options.allowedTools);
|
|
479
713
|
}
|
|
714
|
+
const baseDir = path4.join(__dirname3, "..");
|
|
480
715
|
for (const file of files) {
|
|
481
716
|
const destFileName = prefix + file;
|
|
482
|
-
const destFilePath =
|
|
483
|
-
const sourceFilePath =
|
|
484
|
-
if (await
|
|
485
|
-
const existingContent = await
|
|
486
|
-
|
|
717
|
+
const destFilePath = path4.join(destinationPath, destFileName);
|
|
718
|
+
const sourceFilePath = path4.join(sourcePath, file);
|
|
719
|
+
if (await fs4.pathExists(destFilePath)) {
|
|
720
|
+
const existingContent = await fs4.readFile(destFilePath, "utf-8");
|
|
721
|
+
const sourceContent = await fs4.readFile(sourceFilePath, "utf-8");
|
|
722
|
+
let newContent = applyMarkdownFixes(
|
|
723
|
+
stripInternalMetadata(
|
|
724
|
+
expandContent(sourceContent, {
|
|
725
|
+
flags,
|
|
726
|
+
baseDir
|
|
727
|
+
})
|
|
728
|
+
)
|
|
729
|
+
);
|
|
487
730
|
if (metadata && allowedToolsSet) {
|
|
488
731
|
const commandMetadata = metadata[file];
|
|
489
732
|
const requestedTools = commandMetadata?.[REQUESTED_TOOLS_KEY] || [];
|
|
@@ -518,19 +761,11 @@ var CATEGORY_ORDER = [
|
|
|
518
761
|
"Utilities",
|
|
519
762
|
"Ship / Show / Ask"
|
|
520
763
|
];
|
|
521
|
-
async function loadCommandsMetadata(
|
|
522
|
-
|
|
523
|
-
__dirname2,
|
|
524
|
-
"..",
|
|
525
|
-
DIRECTORIES.DOWNLOADS,
|
|
526
|
-
variant || VARIANTS.WITH_BEADS
|
|
527
|
-
);
|
|
528
|
-
const metadataPath = path2.join(sourcePath, "commands-metadata.json");
|
|
529
|
-
const metadataContent = await fs.readFile(metadataPath, "utf-8");
|
|
530
|
-
return JSON.parse(metadataContent);
|
|
764
|
+
async function loadCommandsMetadata() {
|
|
765
|
+
return generateCommandsMetadata();
|
|
531
766
|
}
|
|
532
|
-
async function getCommandsGroupedByCategory(
|
|
533
|
-
const metadata = await loadCommandsMetadata(
|
|
767
|
+
async function getCommandsGroupedByCategory() {
|
|
768
|
+
const metadata = await loadCommandsMetadata();
|
|
534
769
|
const grouped = {};
|
|
535
770
|
for (const [filename, data] of Object.entries(metadata)) {
|
|
536
771
|
const category = data.category;
|
|
@@ -544,11 +779,6 @@ async function getCommandsGroupedByCategory(variant) {
|
|
|
544
779
|
selectedByDefault: data.selectedByDefault !== false
|
|
545
780
|
});
|
|
546
781
|
}
|
|
547
|
-
for (const category of Object.keys(grouped)) {
|
|
548
|
-
if (!CATEGORY_ORDER.includes(category)) {
|
|
549
|
-
throw new Error(`Unknown category: ${category}`);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
782
|
for (const category of Object.keys(grouped)) {
|
|
553
783
|
grouped[category].sort((a, b) => {
|
|
554
784
|
const orderA = metadata[a.value].order;
|
|
@@ -565,10 +795,6 @@ async function getCommandsGroupedByCategory(variant) {
|
|
|
565
795
|
}
|
|
566
796
|
return sortedGrouped;
|
|
567
797
|
}
|
|
568
|
-
function extractLabelFromTool(tool) {
|
|
569
|
-
const match = tool.match(/^Bash\(([^:]+):/);
|
|
570
|
-
return match ? match[1] : tool;
|
|
571
|
-
}
|
|
572
798
|
function formatCommandsHint(commands) {
|
|
573
799
|
if (commands.length <= 2) {
|
|
574
800
|
return commands.map((c) => `/${c}`).join(", ");
|
|
@@ -577,8 +803,8 @@ function formatCommandsHint(commands) {
|
|
|
577
803
|
const remaining = commands.length - 2;
|
|
578
804
|
return `${first.join(", ")}, and ${remaining} ${remaining === 1 ? "other" : "others"}`;
|
|
579
805
|
}
|
|
580
|
-
async function getRequestedToolsOptions(
|
|
581
|
-
const metadata = await loadCommandsMetadata(
|
|
806
|
+
async function getRequestedToolsOptions() {
|
|
807
|
+
const metadata = await loadCommandsMetadata();
|
|
582
808
|
const toolToCommands = /* @__PURE__ */ new Map();
|
|
583
809
|
for (const [filename, data] of Object.entries(metadata)) {
|
|
584
810
|
if (data[REQUESTED_TOOLS_KEY]) {
|
|
@@ -592,7 +818,7 @@ async function getRequestedToolsOptions(variant) {
|
|
|
592
818
|
}
|
|
593
819
|
return Array.from(toolToCommands.entries()).map(([tool, commands]) => ({
|
|
594
820
|
value: tool,
|
|
595
|
-
label:
|
|
821
|
+
label: tool,
|
|
596
822
|
hint: formatCommandsHint(commands)
|
|
597
823
|
}));
|
|
598
824
|
}
|
|
@@ -601,13 +827,44 @@ function getDestinationPath(outputPath, scope) {
|
|
|
601
827
|
return outputPath;
|
|
602
828
|
}
|
|
603
829
|
if (scope === SCOPES.PROJECT) {
|
|
604
|
-
return
|
|
830
|
+
return path4.join(process.cwd(), DIRECTORIES.CLAUDE, DIRECTORIES.COMMANDS);
|
|
605
831
|
}
|
|
606
832
|
if (scope === SCOPES.USER) {
|
|
607
|
-
return
|
|
833
|
+
return path4.join(os.homedir(), DIRECTORIES.CLAUDE, DIRECTORIES.COMMANDS);
|
|
608
834
|
}
|
|
609
835
|
throw new Error("Either outputPath or scope must be provided");
|
|
610
836
|
}
|
|
837
|
+
function stripInternalMetadata(content) {
|
|
838
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
839
|
+
if (!frontmatterMatch) {
|
|
840
|
+
return content;
|
|
841
|
+
}
|
|
842
|
+
const frontmatter = frontmatterMatch[1];
|
|
843
|
+
const lines = frontmatter.split("\n");
|
|
844
|
+
const filteredLines = [];
|
|
845
|
+
let skipMultiline = false;
|
|
846
|
+
for (const line of lines) {
|
|
847
|
+
if (/^_[\w-]+:/.test(line)) {
|
|
848
|
+
skipMultiline = line.endsWith(":") || /^_[\w-]+:\s*$/.test(line);
|
|
849
|
+
continue;
|
|
850
|
+
}
|
|
851
|
+
if (skipMultiline && /^\s+/.test(line)) {
|
|
852
|
+
continue;
|
|
853
|
+
}
|
|
854
|
+
skipMultiline = false;
|
|
855
|
+
filteredLines.push(line);
|
|
856
|
+
}
|
|
857
|
+
const newFrontmatter = filteredLines.join("\n");
|
|
858
|
+
return content.replace(/^---\n[\s\S]*?\n---/, `---
|
|
859
|
+
${newFrontmatter}
|
|
860
|
+
---`);
|
|
861
|
+
}
|
|
862
|
+
function applyMarkdownFixes(content) {
|
|
863
|
+
const results = lint({
|
|
864
|
+
strings: { content }
|
|
865
|
+
});
|
|
866
|
+
return applyFixes(content, results.content);
|
|
867
|
+
}
|
|
611
868
|
function extractTemplateBlocks(content) {
|
|
612
869
|
const blocks = [];
|
|
613
870
|
const withCommandsRegex = /<claude-commands-template\s+commands="([^"]+)">([\s\S]*?)<\/claude-commands-template>/g;
|
|
@@ -625,34 +882,38 @@ function extractTemplateBlocks(content) {
|
|
|
625
882
|
}
|
|
626
883
|
return blocks;
|
|
627
884
|
}
|
|
628
|
-
async function generateToDirectory(outputPath,
|
|
629
|
-
const sourcePath = path2.join(
|
|
630
|
-
__dirname2,
|
|
631
|
-
"..",
|
|
632
|
-
DIRECTORIES.DOWNLOADS,
|
|
633
|
-
variant || VARIANTS.WITH_BEADS
|
|
634
|
-
);
|
|
885
|
+
async function generateToDirectory(outputPath, scope, options) {
|
|
635
886
|
const destinationPath = getDestinationPath(outputPath, scope);
|
|
636
|
-
const
|
|
887
|
+
const sourcePath = path4.join(__dirname3, "..", DIRECTORIES.SOURCES);
|
|
888
|
+
const flags = options?.flags ?? [];
|
|
889
|
+
const allFiles = (await fs4.readdir(sourcePath)).filter(
|
|
890
|
+
(f) => f.endsWith(".md")
|
|
891
|
+
);
|
|
637
892
|
let files = options?.commands ? allFiles.filter((f) => options.commands.includes(f)) : allFiles;
|
|
638
893
|
if (options?.skipFiles) {
|
|
639
894
|
const prefix2 = options?.commandPrefix || "";
|
|
640
895
|
files = files.filter((f) => !options.skipFiles.includes(prefix2 + f));
|
|
641
896
|
}
|
|
642
897
|
const prefix = options?.commandPrefix || "";
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
898
|
+
await fs4.ensureDir(destinationPath);
|
|
899
|
+
const baseDir = path4.join(__dirname3, "..");
|
|
900
|
+
for (const file of files) {
|
|
901
|
+
const sourceFilePath = path4.join(sourcePath, file);
|
|
902
|
+
const sourceContent = await fs4.readFile(sourceFilePath, "utf-8");
|
|
903
|
+
const expandedContent = expandContent(sourceContent, {
|
|
904
|
+
flags,
|
|
905
|
+
baseDir
|
|
906
|
+
});
|
|
907
|
+
const cleanedContent = applyMarkdownFixes(
|
|
908
|
+
stripInternalMetadata(expandedContent)
|
|
909
|
+
);
|
|
910
|
+
await fs4.writeFile(
|
|
911
|
+
path4.join(destinationPath, prefix + file),
|
|
912
|
+
cleanedContent
|
|
913
|
+
);
|
|
653
914
|
}
|
|
654
915
|
if (options?.allowedTools && options.allowedTools.length > 0) {
|
|
655
|
-
const metadata = await loadCommandsMetadata(
|
|
916
|
+
const metadata = await loadCommandsMetadata();
|
|
656
917
|
const allowedToolsSet = new Set(options.allowedTools);
|
|
657
918
|
for (const file of files) {
|
|
658
919
|
const commandMetadata = metadata[file];
|
|
@@ -661,8 +922,8 @@ async function generateToDirectory(outputPath, variant, scope, options) {
|
|
|
661
922
|
(tool) => allowedToolsSet.has(tool)
|
|
662
923
|
);
|
|
663
924
|
if (toolsForCommand.length > 0) {
|
|
664
|
-
const filePath =
|
|
665
|
-
const content = await
|
|
925
|
+
const filePath = path4.join(destinationPath, prefix + file);
|
|
926
|
+
const content = await fs4.readFile(filePath, "utf-8");
|
|
666
927
|
const allowedToolsYaml = `allowed-tools: ${toolsForCommand.join(", ")}`;
|
|
667
928
|
const modifiedContent = content.replace(
|
|
668
929
|
/^---\n/,
|
|
@@ -670,7 +931,7 @@ async function generateToDirectory(outputPath, variant, scope, options) {
|
|
|
670
931
|
${allowedToolsYaml}
|
|
671
932
|
`
|
|
672
933
|
);
|
|
673
|
-
await
|
|
934
|
+
await fs4.writeFile(filePath, modifiedContent);
|
|
674
935
|
}
|
|
675
936
|
}
|
|
676
937
|
}
|
|
@@ -678,21 +939,21 @@ ${allowedToolsYaml}
|
|
|
678
939
|
if (!options?.skipTemplateInjection) {
|
|
679
940
|
let templateSourcePath = null;
|
|
680
941
|
for (const filename of TEMPLATE_SOURCE_FILES) {
|
|
681
|
-
const candidatePath =
|
|
682
|
-
if (await
|
|
942
|
+
const candidatePath = path4.join(process.cwd(), filename);
|
|
943
|
+
if (await fs4.pathExists(candidatePath)) {
|
|
683
944
|
templateSourcePath = candidatePath;
|
|
684
945
|
break;
|
|
685
946
|
}
|
|
686
947
|
}
|
|
687
948
|
if (templateSourcePath) {
|
|
688
|
-
const sourceContent = await
|
|
949
|
+
const sourceContent = await fs4.readFile(templateSourcePath, "utf-8");
|
|
689
950
|
const templates = extractTemplateBlocks(sourceContent);
|
|
690
951
|
if (templates.length > 0) {
|
|
691
952
|
for (const file of files) {
|
|
692
|
-
const commandName =
|
|
953
|
+
const commandName = path4.basename(file, ".md");
|
|
693
954
|
const actualFileName = options?.commandPrefix ? options.commandPrefix + file : file;
|
|
694
|
-
const filePath =
|
|
695
|
-
let content = await
|
|
955
|
+
const filePath = path4.join(destinationPath, actualFileName);
|
|
956
|
+
let content = await fs4.readFile(filePath, "utf-8");
|
|
696
957
|
let modified = false;
|
|
697
958
|
for (const template of templates) {
|
|
698
959
|
if (template.commands && !template.commands.includes(commandName)) {
|
|
@@ -702,7 +963,7 @@ ${allowedToolsYaml}
|
|
|
702
963
|
modified = true;
|
|
703
964
|
}
|
|
704
965
|
if (modified) {
|
|
705
|
-
await
|
|
966
|
+
await fs4.writeFile(filePath, applyMarkdownFixes(content));
|
|
706
967
|
}
|
|
707
968
|
}
|
|
708
969
|
templateInjected = true;
|
|
@@ -712,88 +973,12 @@ ${allowedToolsYaml}
|
|
|
712
973
|
return {
|
|
713
974
|
success: true,
|
|
714
975
|
filesGenerated: files.length,
|
|
715
|
-
variant,
|
|
716
976
|
templateInjectionSkipped: options?.skipTemplateInjection,
|
|
717
|
-
templateInjected
|
|
977
|
+
templateInjected,
|
|
978
|
+
flags: options?.flags
|
|
718
979
|
};
|
|
719
980
|
}
|
|
720
981
|
|
|
721
|
-
// scripts/cli-options.ts
|
|
722
|
-
init_esm_shims();
|
|
723
|
-
var CLI_OPTIONS = [
|
|
724
|
-
{
|
|
725
|
-
flag: "--variant",
|
|
726
|
-
key: "variant",
|
|
727
|
-
type: "string",
|
|
728
|
-
description: "Command variant (with-beads, without-beads)",
|
|
729
|
-
example: "--variant=with-beads",
|
|
730
|
-
requiredForNonInteractive: true
|
|
731
|
-
},
|
|
732
|
-
{
|
|
733
|
-
flag: "--scope",
|
|
734
|
-
key: "scope",
|
|
735
|
-
type: "string",
|
|
736
|
-
description: "Installation scope (project, user)",
|
|
737
|
-
example: "--scope=project",
|
|
738
|
-
requiredForNonInteractive: true
|
|
739
|
-
},
|
|
740
|
-
{
|
|
741
|
-
flag: "--prefix",
|
|
742
|
-
key: "prefix",
|
|
743
|
-
type: "string",
|
|
744
|
-
description: "Add prefix to command names",
|
|
745
|
-
example: "--prefix=my-"
|
|
746
|
-
},
|
|
747
|
-
{
|
|
748
|
-
flag: "--commands",
|
|
749
|
-
key: "commands",
|
|
750
|
-
type: "array",
|
|
751
|
-
description: "Install only specific commands",
|
|
752
|
-
example: "--commands=commit,red,green"
|
|
753
|
-
},
|
|
754
|
-
{
|
|
755
|
-
flag: "--skip-template-injection",
|
|
756
|
-
key: "skipTemplateInjection",
|
|
757
|
-
type: "boolean",
|
|
758
|
-
description: "Skip injecting project CLAUDE.md customizations"
|
|
759
|
-
},
|
|
760
|
-
{
|
|
761
|
-
flag: "--update-existing",
|
|
762
|
-
key: "updateExisting",
|
|
763
|
-
type: "boolean",
|
|
764
|
-
description: "Only update already-installed commands"
|
|
765
|
-
},
|
|
766
|
-
{
|
|
767
|
-
flag: "--overwrite",
|
|
768
|
-
key: "overwrite",
|
|
769
|
-
type: "boolean",
|
|
770
|
-
description: "Overwrite conflicting files without prompting"
|
|
771
|
-
},
|
|
772
|
-
{
|
|
773
|
-
flag: "--skip-on-conflict",
|
|
774
|
-
key: "skipOnConflict",
|
|
775
|
-
type: "boolean",
|
|
776
|
-
description: "Skip conflicting files without prompting"
|
|
777
|
-
}
|
|
778
|
-
];
|
|
779
|
-
function generateHelpText() {
|
|
780
|
-
const lines = [
|
|
781
|
-
"Usage: npx @wbern/claude-instructions [options]",
|
|
782
|
-
"",
|
|
783
|
-
"Options:"
|
|
784
|
-
];
|
|
785
|
-
for (const opt of CLI_OPTIONS) {
|
|
786
|
-
const suffix = opt.type === "string" ? "=<value>" : opt.type === "array" ? "=<list>" : "";
|
|
787
|
-
const padding = 28 - (opt.flag.length + suffix.length);
|
|
788
|
-
lines.push(
|
|
789
|
-
` ${opt.flag}${suffix}${" ".repeat(Math.max(1, padding))}${opt.description}`
|
|
790
|
-
);
|
|
791
|
-
}
|
|
792
|
-
lines.push(" --help, -h Show this help message");
|
|
793
|
-
lines.push(" --version, -v Show version number");
|
|
794
|
-
return lines.join("\n");
|
|
795
|
-
}
|
|
796
|
-
|
|
797
982
|
// scripts/tty.ts
|
|
798
983
|
init_esm_shims();
|
|
799
984
|
function isInteractiveTTY() {
|
|
@@ -802,6 +987,10 @@ function isInteractiveTTY() {
|
|
|
802
987
|
|
|
803
988
|
// scripts/cli.ts
|
|
804
989
|
var pc = process.env.FORCE_COLOR ? import_picocolors.default.createColors(true) : import_picocolors.default;
|
|
990
|
+
var ScopeValues = Object.values(SCOPES);
|
|
991
|
+
var ScopeSchema = v2.picklist(ScopeValues);
|
|
992
|
+
var FlagValues = FLAG_OPTIONS.map((f) => f.value);
|
|
993
|
+
var FlagsSchema = v2.array(v2.picklist(FlagValues));
|
|
805
994
|
function splitChangeIntoLines(value) {
|
|
806
995
|
const lines = value.split("\n");
|
|
807
996
|
if (lines[lines.length - 1] === "") lines.pop();
|
|
@@ -919,24 +1108,22 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
|
919
1108
|
`;
|
|
920
1109
|
async function main(args) {
|
|
921
1110
|
intro(BATMAN_LOGO);
|
|
922
|
-
let variant;
|
|
923
1111
|
let scope;
|
|
924
1112
|
let commandPrefix;
|
|
925
1113
|
let selectedCommands;
|
|
926
1114
|
let selectedAllowedTools;
|
|
1115
|
+
let selectedFlags;
|
|
927
1116
|
let cachedExistingFiles;
|
|
928
|
-
if (args?.
|
|
929
|
-
|
|
930
|
-
scope = args.scope;
|
|
1117
|
+
if (args?.scope) {
|
|
1118
|
+
scope = v2.parse(ScopeSchema, args.scope);
|
|
931
1119
|
commandPrefix = args.prefix ?? "";
|
|
932
1120
|
selectedCommands = args.commands;
|
|
1121
|
+
selectedFlags = args.flags ? v2.parse(FlagsSchema, args.flags) : void 0;
|
|
933
1122
|
if (args.updateExisting) {
|
|
934
|
-
cachedExistingFiles = await checkExistingFiles(
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
{ commandPrefix: commandPrefix || "" }
|
|
939
|
-
);
|
|
1123
|
+
cachedExistingFiles = await checkExistingFiles(void 0, scope, {
|
|
1124
|
+
commandPrefix: commandPrefix || "",
|
|
1125
|
+
flags: selectedFlags
|
|
1126
|
+
});
|
|
940
1127
|
selectedCommands = cachedExistingFiles.map((f) => f.filename);
|
|
941
1128
|
if (selectedCommands.length === 0) {
|
|
942
1129
|
log.warn("No existing commands found in target directory");
|
|
@@ -951,13 +1138,6 @@ async function main(args) {
|
|
|
951
1138
|
log.warn(`Non-interactive mode requires ${requiredFlags} arguments`);
|
|
952
1139
|
return;
|
|
953
1140
|
}
|
|
954
|
-
variant = await select({
|
|
955
|
-
message: "Select variant",
|
|
956
|
-
options: [...VARIANT_OPTIONS]
|
|
957
|
-
});
|
|
958
|
-
if (isCancel(variant)) {
|
|
959
|
-
return;
|
|
960
|
-
}
|
|
961
1141
|
const terminalWidth = process.stdout.columns || 80;
|
|
962
1142
|
const uiOverhead = 25;
|
|
963
1143
|
scope = await select({
|
|
@@ -974,15 +1154,29 @@ async function main(args) {
|
|
|
974
1154
|
if (isCancel(commandPrefix)) {
|
|
975
1155
|
return;
|
|
976
1156
|
}
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1157
|
+
selectedFlags = await groupMultiselect({
|
|
1158
|
+
message: "Select feature flags (optional)",
|
|
1159
|
+
options: {
|
|
1160
|
+
"Feature Flags": FLAG_OPTIONS.map(({ value, label, hint }) => ({
|
|
1161
|
+
value,
|
|
1162
|
+
label,
|
|
1163
|
+
hint
|
|
1164
|
+
}))
|
|
1165
|
+
},
|
|
1166
|
+
required: false
|
|
1167
|
+
});
|
|
1168
|
+
if (isCancel(selectedFlags)) {
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
let groupedCommands = await getCommandsGroupedByCategory();
|
|
980
1172
|
if (args?.updateExisting) {
|
|
981
1173
|
cachedExistingFiles = await checkExistingFiles(
|
|
982
1174
|
void 0,
|
|
983
|
-
variant,
|
|
984
1175
|
scope,
|
|
985
|
-
{
|
|
1176
|
+
{
|
|
1177
|
+
commandPrefix: commandPrefix || "",
|
|
1178
|
+
flags: selectedFlags
|
|
1179
|
+
}
|
|
986
1180
|
);
|
|
987
1181
|
const existingFilenames = new Set(
|
|
988
1182
|
cachedExistingFiles.map((f) => f.filename)
|
|
@@ -1011,9 +1205,7 @@ async function main(args) {
|
|
|
1011
1205
|
if (isCancel(selectedCommands)) {
|
|
1012
1206
|
return;
|
|
1013
1207
|
}
|
|
1014
|
-
const requestedToolsOptions = await getRequestedToolsOptions(
|
|
1015
|
-
variant
|
|
1016
|
-
);
|
|
1208
|
+
const requestedToolsOptions = await getRequestedToolsOptions();
|
|
1017
1209
|
if (requestedToolsOptions.length > 0) {
|
|
1018
1210
|
selectedAllowedTools = await groupMultiselect({
|
|
1019
1211
|
message: "Select allowed tools for commands (optional)",
|
|
@@ -1027,21 +1219,20 @@ async function main(args) {
|
|
|
1027
1219
|
}
|
|
1028
1220
|
}
|
|
1029
1221
|
}
|
|
1030
|
-
const existingFiles = cachedExistingFiles ?? await checkExistingFiles(void 0,
|
|
1222
|
+
const existingFiles = cachedExistingFiles ?? await checkExistingFiles(void 0, scope, {
|
|
1031
1223
|
commandPrefix,
|
|
1032
1224
|
commands: selectedCommands,
|
|
1033
|
-
allowedTools: selectedAllowedTools
|
|
1225
|
+
allowedTools: selectedAllowedTools,
|
|
1226
|
+
flags: selectedFlags
|
|
1034
1227
|
});
|
|
1035
1228
|
const skipFiles = [];
|
|
1229
|
+
const conflictingFiles = existingFiles.filter((f) => !f.isIdentical);
|
|
1036
1230
|
const shouldSkipConflicts = args?.skipOnConflict || !isInteractiveTTY();
|
|
1037
1231
|
if (args?.overwrite) {
|
|
1038
|
-
for (const file of
|
|
1039
|
-
|
|
1040
|
-
log.info(`Overwriting ${file.filename}`);
|
|
1041
|
-
}
|
|
1232
|
+
for (const file of conflictingFiles) {
|
|
1233
|
+
log.info(`Overwriting ${file.filename}`);
|
|
1042
1234
|
}
|
|
1043
1235
|
} else if (!shouldSkipConflicts) {
|
|
1044
|
-
const conflictingFiles = existingFiles.filter((f) => !f.isIdentical);
|
|
1045
1236
|
const hasMultipleConflicts = conflictingFiles.length > 1;
|
|
1046
1237
|
let overwriteAllSelected = false;
|
|
1047
1238
|
let skipAllSelected = false;
|
|
@@ -1095,31 +1286,25 @@ async function main(args) {
|
|
|
1095
1286
|
}
|
|
1096
1287
|
}
|
|
1097
1288
|
}
|
|
1098
|
-
} else
|
|
1099
|
-
for (const file of
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
log.warn(`Skipping ${file.filename} (conflict)`);
|
|
1103
|
-
}
|
|
1289
|
+
} else {
|
|
1290
|
+
for (const file of conflictingFiles) {
|
|
1291
|
+
skipFiles.push(file.filename);
|
|
1292
|
+
log.warn(`Skipping ${file.filename} (conflict)`);
|
|
1104
1293
|
}
|
|
1105
|
-
if (
|
|
1294
|
+
if (conflictingFiles.length > 0 && !isInteractiveTTY()) {
|
|
1106
1295
|
log.info(
|
|
1107
1296
|
"To resolve conflicts, run interactively or use --overwrite to overwrite"
|
|
1108
1297
|
);
|
|
1109
1298
|
}
|
|
1110
1299
|
}
|
|
1111
|
-
const result = await generateToDirectory(
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
skipFiles,
|
|
1120
|
-
allowedTools: selectedAllowedTools
|
|
1121
|
-
}
|
|
1122
|
-
);
|
|
1300
|
+
const result = await generateToDirectory(void 0, scope, {
|
|
1301
|
+
commandPrefix,
|
|
1302
|
+
skipTemplateInjection: args?.skipTemplateInjection,
|
|
1303
|
+
commands: selectedCommands,
|
|
1304
|
+
skipFiles,
|
|
1305
|
+
allowedTools: selectedAllowedTools,
|
|
1306
|
+
flags: selectedFlags
|
|
1307
|
+
});
|
|
1123
1308
|
const fullPath = scope === "project" ? `${process.cwd()}/.claude/commands` : `${os2.homedir()}/.claude/commands`;
|
|
1124
1309
|
outro(
|
|
1125
1310
|
`Installed ${result.filesGenerated} commands to ${fullPath}
|