@raftlabs/raftstack 1.8.0 → 1.9.1
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/.claude/commands/raftstack/discover.md +205 -0
- package/.claude/commands/raftstack/help.md +309 -0
- package/.claude/commands/raftstack/index.md +259 -0
- package/.claude/commands/raftstack/init-context.md +221 -0
- package/.claude/commands/raftstack/inject.md +244 -0
- package/.claude/commands/raftstack/shape.md +253 -0
- package/README.md +40 -358
- package/README.npm.md +18 -8
- package/dist/cli.js +157 -51
- package/dist/cli.js.map +1 -1
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -1650,14 +1650,65 @@ async function generateClaudeSkills(targetDir, options) {
|
|
|
1650
1650
|
return result;
|
|
1651
1651
|
}
|
|
1652
1652
|
|
|
1653
|
-
// src/generators/
|
|
1653
|
+
// src/generators/claude-commands.ts
|
|
1654
1654
|
import { existsSync as existsSync6 } from "fs";
|
|
1655
|
+
import { readdir as readdir2, copyFile as copyFile3 } from "fs/promises";
|
|
1656
|
+
import { join as join16, dirname as dirname3 } from "path";
|
|
1657
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1658
|
+
function getPackageCommandsDir() {
|
|
1659
|
+
const currentFilePath = fileURLToPath2(import.meta.url);
|
|
1660
|
+
const packageRoot = join16(dirname3(currentFilePath), "..");
|
|
1661
|
+
return join16(packageRoot, ".claude", "commands");
|
|
1662
|
+
}
|
|
1663
|
+
async function copyDirectory2(srcDir, destDir, result, baseDir) {
|
|
1664
|
+
await ensureDir(destDir);
|
|
1665
|
+
const entries = await readdir2(srcDir, { withFileTypes: true });
|
|
1666
|
+
for (const entry of entries) {
|
|
1667
|
+
const srcPath = join16(srcDir, entry.name);
|
|
1668
|
+
const destPath = join16(destDir, entry.name);
|
|
1669
|
+
const relativePath = destPath.replace(baseDir + "/", "");
|
|
1670
|
+
if (entry.isDirectory()) {
|
|
1671
|
+
await copyDirectory2(srcPath, destPath, result, baseDir);
|
|
1672
|
+
} else {
|
|
1673
|
+
if (existsSync6(destPath)) {
|
|
1674
|
+
const backupPath = await backupFile(destPath);
|
|
1675
|
+
if (backupPath) {
|
|
1676
|
+
result.backedUp.push(relativePath);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
await copyFile3(srcPath, destPath);
|
|
1680
|
+
result.created.push(relativePath);
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
async function generateClaudeCommands(targetDir) {
|
|
1685
|
+
const result = {
|
|
1686
|
+
created: [],
|
|
1687
|
+
modified: [],
|
|
1688
|
+
skipped: [],
|
|
1689
|
+
backedUp: []
|
|
1690
|
+
};
|
|
1691
|
+
const packageCommandsDir = getPackageCommandsDir();
|
|
1692
|
+
const targetCommandsDir = join16(targetDir, ".claude", "commands");
|
|
1693
|
+
if (!existsSync6(packageCommandsDir)) {
|
|
1694
|
+
console.warn(
|
|
1695
|
+
"Warning: Commands directory not found in package. Skipping commands generation."
|
|
1696
|
+
);
|
|
1697
|
+
return result;
|
|
1698
|
+
}
|
|
1699
|
+
await ensureDir(join16(targetDir, ".claude"));
|
|
1700
|
+
await copyDirectory2(packageCommandsDir, targetCommandsDir, result, targetDir);
|
|
1701
|
+
return result;
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
// src/generators/eslint.ts
|
|
1705
|
+
import { existsSync as existsSync7 } from "fs";
|
|
1655
1706
|
import { readFile as readFile4 } from "fs/promises";
|
|
1656
|
-
import { join as
|
|
1707
|
+
import { join as join17 } from "path";
|
|
1657
1708
|
async function hasReact(targetDir) {
|
|
1658
1709
|
try {
|
|
1659
|
-
const pkgPath =
|
|
1660
|
-
if (
|
|
1710
|
+
const pkgPath = join17(targetDir, "package.json");
|
|
1711
|
+
if (existsSync7(pkgPath)) {
|
|
1661
1712
|
const content = await readFile4(pkgPath, "utf-8");
|
|
1662
1713
|
const pkg = JSON.parse(content);
|
|
1663
1714
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
@@ -1669,8 +1720,8 @@ async function hasReact(targetDir) {
|
|
|
1669
1720
|
}
|
|
1670
1721
|
async function hasNextJs(targetDir) {
|
|
1671
1722
|
try {
|
|
1672
|
-
const pkgPath =
|
|
1673
|
-
if (
|
|
1723
|
+
const pkgPath = join17(targetDir, "package.json");
|
|
1724
|
+
if (existsSync7(pkgPath)) {
|
|
1674
1725
|
const content = await readFile4(pkgPath, "utf-8");
|
|
1675
1726
|
const pkg = JSON.parse(content);
|
|
1676
1727
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
@@ -1949,7 +2000,7 @@ async function generateEslint(targetDir, usesTypeScript, force = false) {
|
|
|
1949
2000
|
} else {
|
|
1950
2001
|
config = generateJsConfig();
|
|
1951
2002
|
}
|
|
1952
|
-
const configPath =
|
|
2003
|
+
const configPath = join17(targetDir, "eslint.config.mjs");
|
|
1953
2004
|
const writeResult = await writeFileSafe(configPath, config);
|
|
1954
2005
|
if (writeResult.backedUp) {
|
|
1955
2006
|
result.backedUp.push("eslint.config.mjs");
|
|
@@ -1959,7 +2010,7 @@ async function generateEslint(targetDir, usesTypeScript, force = false) {
|
|
|
1959
2010
|
}
|
|
1960
2011
|
|
|
1961
2012
|
// src/generators/quick-reference.ts
|
|
1962
|
-
import { join as
|
|
2013
|
+
import { join as join18 } from "path";
|
|
1963
2014
|
async function generateQuickReference(targetDir, pm) {
|
|
1964
2015
|
const result = {
|
|
1965
2016
|
created: [],
|
|
@@ -1967,7 +2018,7 @@ async function generateQuickReference(targetDir, pm) {
|
|
|
1967
2018
|
skipped: [],
|
|
1968
2019
|
backedUp: []
|
|
1969
2020
|
};
|
|
1970
|
-
const quickRefPath =
|
|
2021
|
+
const quickRefPath = join18(targetDir, ".github", "QUICK_REFERENCE.md");
|
|
1971
2022
|
const content = `# RaftStack Quick Reference
|
|
1972
2023
|
|
|
1973
2024
|
> One-page guide for the RaftStack Git workflow
|
|
@@ -2101,7 +2152,7 @@ ${pm.run} test
|
|
|
2101
2152
|
}
|
|
2102
2153
|
|
|
2103
2154
|
// src/generators/shared-configs.ts
|
|
2104
|
-
import { join as
|
|
2155
|
+
import { join as join19 } from "path";
|
|
2105
2156
|
function getEslintConfigPackageJson() {
|
|
2106
2157
|
return JSON.stringify(
|
|
2107
2158
|
{
|
|
@@ -2367,15 +2418,15 @@ async function generateSharedConfigs(targetDir, projectType) {
|
|
|
2367
2418
|
if (!isMonorepo(projectType)) {
|
|
2368
2419
|
return result;
|
|
2369
2420
|
}
|
|
2370
|
-
const packagesDir =
|
|
2371
|
-
const eslintConfigDir =
|
|
2421
|
+
const packagesDir = join19(targetDir, "packages");
|
|
2422
|
+
const eslintConfigDir = join19(packagesDir, "eslint-config");
|
|
2372
2423
|
await ensureDir(eslintConfigDir);
|
|
2373
2424
|
const eslintFiles = [
|
|
2374
|
-
{ path:
|
|
2375
|
-
{ path:
|
|
2376
|
-
{ path:
|
|
2377
|
-
{ path:
|
|
2378
|
-
{ path:
|
|
2425
|
+
{ path: join19(eslintConfigDir, "package.json"), content: getEslintConfigPackageJson(), name: "packages/eslint-config/package.json" },
|
|
2426
|
+
{ path: join19(eslintConfigDir, "base.js"), content: getBaseEslintConfig(), name: "packages/eslint-config/base.js" },
|
|
2427
|
+
{ path: join19(eslintConfigDir, "next.js"), content: getNextJsEslintConfig(), name: "packages/eslint-config/next.js" },
|
|
2428
|
+
{ path: join19(eslintConfigDir, "react-internal.js"), content: getReactInternalEslintConfig(), name: "packages/eslint-config/react-internal.js" },
|
|
2429
|
+
{ path: join19(eslintConfigDir, "vite.js"), content: getViteEslintConfig(), name: "packages/eslint-config/vite.js" }
|
|
2379
2430
|
];
|
|
2380
2431
|
for (const file of eslintFiles) {
|
|
2381
2432
|
const writeResult = await writeFileSafe(file.path, file.content, { backup: true });
|
|
@@ -2386,14 +2437,14 @@ async function generateSharedConfigs(targetDir, projectType) {
|
|
|
2386
2437
|
}
|
|
2387
2438
|
}
|
|
2388
2439
|
}
|
|
2389
|
-
const tsConfigDir =
|
|
2440
|
+
const tsConfigDir = join19(packagesDir, "typescript-config");
|
|
2390
2441
|
await ensureDir(tsConfigDir);
|
|
2391
2442
|
const tsFiles = [
|
|
2392
|
-
{ path:
|
|
2393
|
-
{ path:
|
|
2394
|
-
{ path:
|
|
2395
|
-
{ path:
|
|
2396
|
-
{ path:
|
|
2443
|
+
{ path: join19(tsConfigDir, "package.json"), content: getTsConfigPackageJson(), name: "packages/typescript-config/package.json" },
|
|
2444
|
+
{ path: join19(tsConfigDir, "base.json"), content: getBaseTsConfig(), name: "packages/typescript-config/base.json" },
|
|
2445
|
+
{ path: join19(tsConfigDir, "nextjs.json"), content: getNextJsTsConfig(), name: "packages/typescript-config/nextjs.json" },
|
|
2446
|
+
{ path: join19(tsConfigDir, "react-library.json"), content: getReactLibraryTsConfig(), name: "packages/typescript-config/react-library.json" },
|
|
2447
|
+
{ path: join19(tsConfigDir, "node-library.json"), content: getNodeLibraryTsConfig(), name: "packages/typescript-config/node-library.json" }
|
|
2397
2448
|
];
|
|
2398
2449
|
for (const file of tsFiles) {
|
|
2399
2450
|
const writeResult = await writeFileSafe(file.path, file.content, { backup: true });
|
|
@@ -2409,10 +2460,10 @@ async function generateSharedConfigs(targetDir, projectType) {
|
|
|
2409
2460
|
|
|
2410
2461
|
// src/utils/git.ts
|
|
2411
2462
|
import { execa } from "execa";
|
|
2412
|
-
import { existsSync as
|
|
2413
|
-
import { join as
|
|
2463
|
+
import { existsSync as existsSync8 } from "fs";
|
|
2464
|
+
import { join as join20 } from "path";
|
|
2414
2465
|
async function isGitRepo(targetDir = process.cwd()) {
|
|
2415
|
-
if (
|
|
2466
|
+
if (existsSync8(join20(targetDir, ".git"))) {
|
|
2416
2467
|
return true;
|
|
2417
2468
|
}
|
|
2418
2469
|
try {
|
|
@@ -2548,8 +2599,8 @@ async function runInit(targetDir = process.cwd()) {
|
|
|
2548
2599
|
);
|
|
2549
2600
|
installFailed = true;
|
|
2550
2601
|
}
|
|
2551
|
-
const
|
|
2552
|
-
|
|
2602
|
+
const spinner5 = p2.spinner();
|
|
2603
|
+
spinner5.start("Generating configuration files...");
|
|
2553
2604
|
const results = [];
|
|
2554
2605
|
try {
|
|
2555
2606
|
results.push(
|
|
@@ -2584,10 +2635,11 @@ async function runInit(targetDir = process.cwd()) {
|
|
|
2584
2635
|
results.push(await generateClaudeSkills(targetDir, {
|
|
2585
2636
|
includeAsana: !!config.asanaBaseUrl
|
|
2586
2637
|
}));
|
|
2638
|
+
results.push(await generateClaudeCommands(targetDir));
|
|
2587
2639
|
results.push(await updateProjectPackageJson(targetDir, config));
|
|
2588
|
-
|
|
2640
|
+
spinner5.stop("Configuration files generated!");
|
|
2589
2641
|
} catch (error) {
|
|
2590
|
-
|
|
2642
|
+
spinner5.stop("Error generating files");
|
|
2591
2643
|
p2.log.error(
|
|
2592
2644
|
pc2.red(
|
|
2593
2645
|
`Error: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
@@ -2735,11 +2787,11 @@ async function applyMergeStrategy(owner, repo, settings) {
|
|
|
2735
2787
|
async function runSetupProtection(targetDir = process.cwd()) {
|
|
2736
2788
|
console.log();
|
|
2737
2789
|
p3.intro(pc3.bgCyan(pc3.black(" Branch Protection Setup ")));
|
|
2738
|
-
const
|
|
2739
|
-
|
|
2790
|
+
const spinner5 = p3.spinner();
|
|
2791
|
+
spinner5.start("Checking GitHub CLI...");
|
|
2740
2792
|
const ghAvailable = await isGhCliAvailable();
|
|
2741
2793
|
if (!ghAvailable) {
|
|
2742
|
-
|
|
2794
|
+
spinner5.stop("GitHub CLI not found or not authenticated");
|
|
2743
2795
|
console.log();
|
|
2744
2796
|
p3.log.error(pc3.red("The GitHub CLI (gh) is required for this command."));
|
|
2745
2797
|
p3.log.info("Install it from: https://cli.github.com/");
|
|
@@ -2752,18 +2804,18 @@ async function runSetupProtection(targetDir = process.cwd()) {
|
|
|
2752
2804
|
);
|
|
2753
2805
|
process.exit(1);
|
|
2754
2806
|
}
|
|
2755
|
-
|
|
2756
|
-
|
|
2807
|
+
spinner5.stop("GitHub CLI ready");
|
|
2808
|
+
spinner5.start("Getting repository info...");
|
|
2757
2809
|
const repoInfo = await getGitHubRepoInfo(targetDir);
|
|
2758
2810
|
if (!repoInfo) {
|
|
2759
|
-
|
|
2811
|
+
spinner5.stop("Could not determine repository");
|
|
2760
2812
|
p3.log.error(
|
|
2761
2813
|
pc3.red("Could not determine the GitHub repository for this directory.")
|
|
2762
2814
|
);
|
|
2763
2815
|
p3.log.info("Make sure you're in a git repository with a GitHub remote.");
|
|
2764
2816
|
process.exit(1);
|
|
2765
2817
|
}
|
|
2766
|
-
|
|
2818
|
+
spinner5.stop(`Repository: ${pc3.cyan(`${repoInfo.owner}/${repoInfo.repo}`)}`);
|
|
2767
2819
|
const branches = await p3.multiselect({
|
|
2768
2820
|
message: "Which branches need protection?",
|
|
2769
2821
|
options: [
|
|
@@ -2852,13 +2904,13 @@ async function runSetupProtection(targetDir = process.cwd()) {
|
|
|
2852
2904
|
p3.cancel("Setup cancelled.");
|
|
2853
2905
|
process.exit(0);
|
|
2854
2906
|
}
|
|
2855
|
-
|
|
2907
|
+
spinner5.start("Configuring merge strategy...");
|
|
2856
2908
|
try {
|
|
2857
2909
|
const repoSettings = getMergeStrategySettings(mergeStrategy);
|
|
2858
2910
|
await applyMergeStrategy(repoInfo.owner, repoInfo.repo, repoSettings);
|
|
2859
|
-
|
|
2911
|
+
spinner5.stop("Merge strategy configured!");
|
|
2860
2912
|
} catch (error) {
|
|
2861
|
-
|
|
2913
|
+
spinner5.stop("Failed to configure merge strategy");
|
|
2862
2914
|
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
2863
2915
|
p3.log.warn(pc3.yellow(`Warning: Could not set merge strategy: ${errorMsg}`));
|
|
2864
2916
|
p3.log.info(pc3.dim("Continuing with branch protection..."));
|
|
@@ -2866,16 +2918,16 @@ async function runSetupProtection(targetDir = process.cwd()) {
|
|
|
2866
2918
|
const protectedBranches = [];
|
|
2867
2919
|
const failedBranches = [];
|
|
2868
2920
|
for (const branch of branches) {
|
|
2869
|
-
|
|
2921
|
+
spinner5.start(`Protecting branch: ${branch}...`);
|
|
2870
2922
|
try {
|
|
2871
2923
|
const settings = getDefaultSettings(branch);
|
|
2872
2924
|
settings.requiredReviews = requiredReviews;
|
|
2873
2925
|
await applyBranchProtection(repoInfo.owner, repoInfo.repo, settings);
|
|
2874
2926
|
protectedBranches.push(branch);
|
|
2875
|
-
|
|
2927
|
+
spinner5.stop(`Protected: ${pc3.green(branch)}`);
|
|
2876
2928
|
} catch (error) {
|
|
2877
2929
|
failedBranches.push(branch);
|
|
2878
|
-
|
|
2930
|
+
spinner5.stop(`Failed: ${pc3.red(branch)}`);
|
|
2879
2931
|
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
2880
2932
|
p3.log.warn(
|
|
2881
2933
|
pc3.yellow(
|
|
@@ -3398,8 +3450,8 @@ async function runMetrics(targetDir, options = {}) {
|
|
|
3398
3450
|
selectedDays = daysOption;
|
|
3399
3451
|
}
|
|
3400
3452
|
const analyzeDays = selectedDays || 30;
|
|
3401
|
-
const
|
|
3402
|
-
|
|
3453
|
+
const spinner5 = ciMode ? null : p4.spinner();
|
|
3454
|
+
spinner5?.start("Analyzing repository...");
|
|
3403
3455
|
let overallCompliance = 100;
|
|
3404
3456
|
const complianceScores = [];
|
|
3405
3457
|
if (showGit) {
|
|
@@ -3420,7 +3472,7 @@ async function runMetrics(targetDir, options = {}) {
|
|
|
3420
3472
|
conventionalCompliance,
|
|
3421
3473
|
branchMetrics.branchCompliance
|
|
3422
3474
|
);
|
|
3423
|
-
|
|
3475
|
+
spinner5?.stop("Git analysis complete");
|
|
3424
3476
|
if (ciMode) {
|
|
3425
3477
|
console.log("\n=== GIT METRICS ===");
|
|
3426
3478
|
console.log(`Commits (last ${analyzeDays} days): ${totalCommits}`);
|
|
@@ -3478,13 +3530,13 @@ ${pc4.bold("Branches")}
|
|
|
3478
3530
|
}
|
|
3479
3531
|
if (showCode) {
|
|
3480
3532
|
if (!ciMode && showGit) {
|
|
3481
|
-
|
|
3533
|
+
spinner5?.start("Analyzing codebase...");
|
|
3482
3534
|
} else if (!ciMode) {
|
|
3483
|
-
|
|
3535
|
+
spinner5?.start("Analyzing codebase...");
|
|
3484
3536
|
}
|
|
3485
3537
|
const codebaseMetrics = await analyzeCodebase(targetDir);
|
|
3486
3538
|
complianceScores.push(codebaseMetrics.overallCompliance);
|
|
3487
|
-
|
|
3539
|
+
spinner5?.stop("Codebase analysis complete");
|
|
3488
3540
|
if (ciMode) {
|
|
3489
3541
|
console.log("\n=== CODEBASE METRICS ===");
|
|
3490
3542
|
console.log(`Files analyzed: ${codebaseMetrics.filesAnalyzed}`);
|
|
@@ -3528,10 +3580,60 @@ PASSED: Compliance meets threshold`);
|
|
|
3528
3580
|
}
|
|
3529
3581
|
}
|
|
3530
3582
|
|
|
3583
|
+
// src/commands/install-commands.ts
|
|
3584
|
+
import * as p5 from "@clack/prompts";
|
|
3585
|
+
import pc5 from "picocolors";
|
|
3586
|
+
async function runInstallCommands(targetDir = process.cwd()) {
|
|
3587
|
+
p5.intro(pc5.cyan("RaftStack: Install Claude Code commands and skills"));
|
|
3588
|
+
const spinner5 = p5.spinner();
|
|
3589
|
+
spinner5.start("Installing Claude Code commands and skills...");
|
|
3590
|
+
try {
|
|
3591
|
+
const commandsResult = await generateClaudeCommands(targetDir);
|
|
3592
|
+
const skillsResult = await generateClaudeSkills(targetDir);
|
|
3593
|
+
spinner5.stop("Claude Code commands and skills installed!");
|
|
3594
|
+
const created = [...commandsResult.created, ...skillsResult.created];
|
|
3595
|
+
const backedUp = [...commandsResult.backedUp, ...skillsResult.backedUp];
|
|
3596
|
+
console.log();
|
|
3597
|
+
if (created.length > 0) {
|
|
3598
|
+
p5.log.success(pc5.green("Installed files:"));
|
|
3599
|
+
for (const file of created) {
|
|
3600
|
+
console.log(` ${pc5.dim("+")} ${file}`);
|
|
3601
|
+
}
|
|
3602
|
+
}
|
|
3603
|
+
if (backedUp.length > 0) {
|
|
3604
|
+
console.log();
|
|
3605
|
+
p5.log.info(pc5.dim("Backed up existing files:"));
|
|
3606
|
+
for (const file of backedUp) {
|
|
3607
|
+
console.log(` ${pc5.dim("\u2192")} ${file}.backup`);
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3610
|
+
console.log();
|
|
3611
|
+
p5.note(
|
|
3612
|
+
[
|
|
3613
|
+
`${pc5.cyan("/raftstack/init-context")} - Analyze codebase, generate constitution`,
|
|
3614
|
+
`${pc5.cyan("/raftstack/shape")} - Plan features with adaptive depth`,
|
|
3615
|
+
`${pc5.cyan("/raftstack/discover")} - Extract patterns into standards`,
|
|
3616
|
+
`${pc5.cyan("/raftstack/inject")} - Surface relevant context for tasks`,
|
|
3617
|
+
`${pc5.cyan("/raftstack/index")} - Maintain standards registry`
|
|
3618
|
+
].join("\n"),
|
|
3619
|
+
"Available Commands"
|
|
3620
|
+
);
|
|
3621
|
+
p5.outro(pc5.green("Ready to use! Try /raftstack/init-context to get started."));
|
|
3622
|
+
} catch (error) {
|
|
3623
|
+
spinner5.stop("Error installing commands");
|
|
3624
|
+
p5.log.error(
|
|
3625
|
+
pc5.red(
|
|
3626
|
+
`Error: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
3627
|
+
)
|
|
3628
|
+
);
|
|
3629
|
+
process.exit(1);
|
|
3630
|
+
}
|
|
3631
|
+
}
|
|
3632
|
+
|
|
3531
3633
|
// package.json
|
|
3532
3634
|
var package_default = {
|
|
3533
3635
|
name: "@raftlabs/raftstack",
|
|
3534
|
-
version: "1.
|
|
3636
|
+
version: "1.9.1",
|
|
3535
3637
|
description: "CLI tool for setting up Git hooks, commit conventions, and GitHub integration",
|
|
3536
3638
|
type: "module",
|
|
3537
3639
|
main: "./dist/index.js",
|
|
@@ -3548,7 +3650,8 @@ var package_default = {
|
|
|
3548
3650
|
files: [
|
|
3549
3651
|
"dist",
|
|
3550
3652
|
"templates",
|
|
3551
|
-
".claude/skills"
|
|
3653
|
+
".claude/skills",
|
|
3654
|
+
".claude/commands"
|
|
3552
3655
|
],
|
|
3553
3656
|
scripts: {
|
|
3554
3657
|
build: "tsup",
|
|
@@ -3636,5 +3739,8 @@ program.command("metrics").description("Analyze repository compliance with RaftS
|
|
|
3636
3739
|
});
|
|
3637
3740
|
}
|
|
3638
3741
|
);
|
|
3742
|
+
program.command("install-commands").description("Install or update Claude Code commands and skills").action(async () => {
|
|
3743
|
+
await runInstallCommands(process.cwd());
|
|
3744
|
+
});
|
|
3639
3745
|
program.parse();
|
|
3640
3746
|
//# sourceMappingURL=cli.js.map
|