@raftlabs/raftstack 1.8.0 → 1.9.2
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/.claude/settings.json +3 -0
- package/.claude/subagents/quick-fix.md +21 -0
- package/README.md +40 -358
- package/README.npm.md +18 -8
- package/dist/cli.js +225 -51
- package/dist/cli.js.map +1 -1
- package/package.json +5 -2
package/dist/cli.js
CHANGED
|
@@ -1650,14 +1650,130 @@ 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/claude-config.ts
|
|
1705
|
+
import { existsSync as existsSync7 } from "fs";
|
|
1706
|
+
import { readdir as readdir3, copyFile as copyFile4 } from "fs/promises";
|
|
1707
|
+
import { join as join17, dirname as dirname4 } from "path";
|
|
1708
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1709
|
+
function getPackageConfigDir() {
|
|
1710
|
+
const currentFilePath = fileURLToPath3(import.meta.url);
|
|
1711
|
+
const packageRoot = join17(dirname4(currentFilePath), "..");
|
|
1712
|
+
return join17(packageRoot, ".claude");
|
|
1713
|
+
}
|
|
1714
|
+
async function copyDirectory3(srcDir, destDir, result, baseDir) {
|
|
1715
|
+
await ensureDir(destDir);
|
|
1716
|
+
const entries = await readdir3(srcDir, { withFileTypes: true });
|
|
1717
|
+
for (const entry of entries) {
|
|
1718
|
+
const srcPath = join17(srcDir, entry.name);
|
|
1719
|
+
const destPath = join17(destDir, entry.name);
|
|
1720
|
+
const relativePath = destPath.replace(baseDir + "/", "");
|
|
1721
|
+
if (entry.isDirectory()) {
|
|
1722
|
+
await copyDirectory3(srcPath, destPath, result, baseDir);
|
|
1723
|
+
} else {
|
|
1724
|
+
if (existsSync7(destPath)) {
|
|
1725
|
+
const backupPath = await backupFile(destPath);
|
|
1726
|
+
if (backupPath) {
|
|
1727
|
+
result.backedUp.push(relativePath);
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
await copyFile4(srcPath, destPath);
|
|
1731
|
+
result.created.push(relativePath);
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
async function generateClaudeConfig(targetDir) {
|
|
1736
|
+
const result = {
|
|
1737
|
+
created: [],
|
|
1738
|
+
modified: [],
|
|
1739
|
+
skipped: [],
|
|
1740
|
+
backedUp: []
|
|
1741
|
+
};
|
|
1742
|
+
const packageConfigDir = getPackageConfigDir();
|
|
1743
|
+
const targetClaudeDir = join17(targetDir, ".claude");
|
|
1744
|
+
await ensureDir(targetClaudeDir);
|
|
1745
|
+
const settingsContent = JSON.stringify({ model: "opusplan" }, null, 2) + "\n";
|
|
1746
|
+
const settingsResult = await writeFileSafe(
|
|
1747
|
+
join17(targetClaudeDir, "settings.json"),
|
|
1748
|
+
settingsContent,
|
|
1749
|
+
{ backup: true }
|
|
1750
|
+
);
|
|
1751
|
+
if (settingsResult.created) {
|
|
1752
|
+
result.created.push(".claude/settings.json");
|
|
1753
|
+
if (settingsResult.backedUp) {
|
|
1754
|
+
result.backedUp.push(settingsResult.backedUp);
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
const packageSubagentsDir = join17(packageConfigDir, "subagents");
|
|
1758
|
+
const targetSubagentsDir = join17(targetClaudeDir, "subagents");
|
|
1759
|
+
if (existsSync7(packageSubagentsDir)) {
|
|
1760
|
+
await copyDirectory3(packageSubagentsDir, targetSubagentsDir, result, targetDir);
|
|
1761
|
+
} else {
|
|
1762
|
+
console.warn(
|
|
1763
|
+
"Warning: Subagents directory not found in package. Skipping subagents generation."
|
|
1764
|
+
);
|
|
1765
|
+
}
|
|
1766
|
+
return result;
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
// src/generators/eslint.ts
|
|
1770
|
+
import { existsSync as existsSync8 } from "fs";
|
|
1655
1771
|
import { readFile as readFile4 } from "fs/promises";
|
|
1656
|
-
import { join as
|
|
1772
|
+
import { join as join18 } from "path";
|
|
1657
1773
|
async function hasReact(targetDir) {
|
|
1658
1774
|
try {
|
|
1659
|
-
const pkgPath =
|
|
1660
|
-
if (
|
|
1775
|
+
const pkgPath = join18(targetDir, "package.json");
|
|
1776
|
+
if (existsSync8(pkgPath)) {
|
|
1661
1777
|
const content = await readFile4(pkgPath, "utf-8");
|
|
1662
1778
|
const pkg = JSON.parse(content);
|
|
1663
1779
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
@@ -1669,8 +1785,8 @@ async function hasReact(targetDir) {
|
|
|
1669
1785
|
}
|
|
1670
1786
|
async function hasNextJs(targetDir) {
|
|
1671
1787
|
try {
|
|
1672
|
-
const pkgPath =
|
|
1673
|
-
if (
|
|
1788
|
+
const pkgPath = join18(targetDir, "package.json");
|
|
1789
|
+
if (existsSync8(pkgPath)) {
|
|
1674
1790
|
const content = await readFile4(pkgPath, "utf-8");
|
|
1675
1791
|
const pkg = JSON.parse(content);
|
|
1676
1792
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
@@ -1949,7 +2065,7 @@ async function generateEslint(targetDir, usesTypeScript, force = false) {
|
|
|
1949
2065
|
} else {
|
|
1950
2066
|
config = generateJsConfig();
|
|
1951
2067
|
}
|
|
1952
|
-
const configPath =
|
|
2068
|
+
const configPath = join18(targetDir, "eslint.config.mjs");
|
|
1953
2069
|
const writeResult = await writeFileSafe(configPath, config);
|
|
1954
2070
|
if (writeResult.backedUp) {
|
|
1955
2071
|
result.backedUp.push("eslint.config.mjs");
|
|
@@ -1959,7 +2075,7 @@ async function generateEslint(targetDir, usesTypeScript, force = false) {
|
|
|
1959
2075
|
}
|
|
1960
2076
|
|
|
1961
2077
|
// src/generators/quick-reference.ts
|
|
1962
|
-
import { join as
|
|
2078
|
+
import { join as join19 } from "path";
|
|
1963
2079
|
async function generateQuickReference(targetDir, pm) {
|
|
1964
2080
|
const result = {
|
|
1965
2081
|
created: [],
|
|
@@ -1967,7 +2083,7 @@ async function generateQuickReference(targetDir, pm) {
|
|
|
1967
2083
|
skipped: [],
|
|
1968
2084
|
backedUp: []
|
|
1969
2085
|
};
|
|
1970
|
-
const quickRefPath =
|
|
2086
|
+
const quickRefPath = join19(targetDir, ".github", "QUICK_REFERENCE.md");
|
|
1971
2087
|
const content = `# RaftStack Quick Reference
|
|
1972
2088
|
|
|
1973
2089
|
> One-page guide for the RaftStack Git workflow
|
|
@@ -2101,7 +2217,7 @@ ${pm.run} test
|
|
|
2101
2217
|
}
|
|
2102
2218
|
|
|
2103
2219
|
// src/generators/shared-configs.ts
|
|
2104
|
-
import { join as
|
|
2220
|
+
import { join as join20 } from "path";
|
|
2105
2221
|
function getEslintConfigPackageJson() {
|
|
2106
2222
|
return JSON.stringify(
|
|
2107
2223
|
{
|
|
@@ -2367,15 +2483,15 @@ async function generateSharedConfigs(targetDir, projectType) {
|
|
|
2367
2483
|
if (!isMonorepo(projectType)) {
|
|
2368
2484
|
return result;
|
|
2369
2485
|
}
|
|
2370
|
-
const packagesDir =
|
|
2371
|
-
const eslintConfigDir =
|
|
2486
|
+
const packagesDir = join20(targetDir, "packages");
|
|
2487
|
+
const eslintConfigDir = join20(packagesDir, "eslint-config");
|
|
2372
2488
|
await ensureDir(eslintConfigDir);
|
|
2373
2489
|
const eslintFiles = [
|
|
2374
|
-
{ path:
|
|
2375
|
-
{ path:
|
|
2376
|
-
{ path:
|
|
2377
|
-
{ path:
|
|
2378
|
-
{ path:
|
|
2490
|
+
{ path: join20(eslintConfigDir, "package.json"), content: getEslintConfigPackageJson(), name: "packages/eslint-config/package.json" },
|
|
2491
|
+
{ path: join20(eslintConfigDir, "base.js"), content: getBaseEslintConfig(), name: "packages/eslint-config/base.js" },
|
|
2492
|
+
{ path: join20(eslintConfigDir, "next.js"), content: getNextJsEslintConfig(), name: "packages/eslint-config/next.js" },
|
|
2493
|
+
{ path: join20(eslintConfigDir, "react-internal.js"), content: getReactInternalEslintConfig(), name: "packages/eslint-config/react-internal.js" },
|
|
2494
|
+
{ path: join20(eslintConfigDir, "vite.js"), content: getViteEslintConfig(), name: "packages/eslint-config/vite.js" }
|
|
2379
2495
|
];
|
|
2380
2496
|
for (const file of eslintFiles) {
|
|
2381
2497
|
const writeResult = await writeFileSafe(file.path, file.content, { backup: true });
|
|
@@ -2386,14 +2502,14 @@ async function generateSharedConfigs(targetDir, projectType) {
|
|
|
2386
2502
|
}
|
|
2387
2503
|
}
|
|
2388
2504
|
}
|
|
2389
|
-
const tsConfigDir =
|
|
2505
|
+
const tsConfigDir = join20(packagesDir, "typescript-config");
|
|
2390
2506
|
await ensureDir(tsConfigDir);
|
|
2391
2507
|
const tsFiles = [
|
|
2392
|
-
{ path:
|
|
2393
|
-
{ path:
|
|
2394
|
-
{ path:
|
|
2395
|
-
{ path:
|
|
2396
|
-
{ path:
|
|
2508
|
+
{ path: join20(tsConfigDir, "package.json"), content: getTsConfigPackageJson(), name: "packages/typescript-config/package.json" },
|
|
2509
|
+
{ path: join20(tsConfigDir, "base.json"), content: getBaseTsConfig(), name: "packages/typescript-config/base.json" },
|
|
2510
|
+
{ path: join20(tsConfigDir, "nextjs.json"), content: getNextJsTsConfig(), name: "packages/typescript-config/nextjs.json" },
|
|
2511
|
+
{ path: join20(tsConfigDir, "react-library.json"), content: getReactLibraryTsConfig(), name: "packages/typescript-config/react-library.json" },
|
|
2512
|
+
{ path: join20(tsConfigDir, "node-library.json"), content: getNodeLibraryTsConfig(), name: "packages/typescript-config/node-library.json" }
|
|
2397
2513
|
];
|
|
2398
2514
|
for (const file of tsFiles) {
|
|
2399
2515
|
const writeResult = await writeFileSafe(file.path, file.content, { backup: true });
|
|
@@ -2409,10 +2525,10 @@ async function generateSharedConfigs(targetDir, projectType) {
|
|
|
2409
2525
|
|
|
2410
2526
|
// src/utils/git.ts
|
|
2411
2527
|
import { execa } from "execa";
|
|
2412
|
-
import { existsSync as
|
|
2413
|
-
import { join as
|
|
2528
|
+
import { existsSync as existsSync9 } from "fs";
|
|
2529
|
+
import { join as join21 } from "path";
|
|
2414
2530
|
async function isGitRepo(targetDir = process.cwd()) {
|
|
2415
|
-
if (
|
|
2531
|
+
if (existsSync9(join21(targetDir, ".git"))) {
|
|
2416
2532
|
return true;
|
|
2417
2533
|
}
|
|
2418
2534
|
try {
|
|
@@ -2548,8 +2664,8 @@ async function runInit(targetDir = process.cwd()) {
|
|
|
2548
2664
|
);
|
|
2549
2665
|
installFailed = true;
|
|
2550
2666
|
}
|
|
2551
|
-
const
|
|
2552
|
-
|
|
2667
|
+
const spinner5 = p2.spinner();
|
|
2668
|
+
spinner5.start("Generating configuration files...");
|
|
2553
2669
|
const results = [];
|
|
2554
2670
|
try {
|
|
2555
2671
|
results.push(
|
|
@@ -2584,10 +2700,12 @@ async function runInit(targetDir = process.cwd()) {
|
|
|
2584
2700
|
results.push(await generateClaudeSkills(targetDir, {
|
|
2585
2701
|
includeAsana: !!config.asanaBaseUrl
|
|
2586
2702
|
}));
|
|
2703
|
+
results.push(await generateClaudeCommands(targetDir));
|
|
2704
|
+
results.push(await generateClaudeConfig(targetDir));
|
|
2587
2705
|
results.push(await updateProjectPackageJson(targetDir, config));
|
|
2588
|
-
|
|
2706
|
+
spinner5.stop("Configuration files generated!");
|
|
2589
2707
|
} catch (error) {
|
|
2590
|
-
|
|
2708
|
+
spinner5.stop("Error generating files");
|
|
2591
2709
|
p2.log.error(
|
|
2592
2710
|
pc2.red(
|
|
2593
2711
|
`Error: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
@@ -2735,11 +2853,11 @@ async function applyMergeStrategy(owner, repo, settings) {
|
|
|
2735
2853
|
async function runSetupProtection(targetDir = process.cwd()) {
|
|
2736
2854
|
console.log();
|
|
2737
2855
|
p3.intro(pc3.bgCyan(pc3.black(" Branch Protection Setup ")));
|
|
2738
|
-
const
|
|
2739
|
-
|
|
2856
|
+
const spinner5 = p3.spinner();
|
|
2857
|
+
spinner5.start("Checking GitHub CLI...");
|
|
2740
2858
|
const ghAvailable = await isGhCliAvailable();
|
|
2741
2859
|
if (!ghAvailable) {
|
|
2742
|
-
|
|
2860
|
+
spinner5.stop("GitHub CLI not found or not authenticated");
|
|
2743
2861
|
console.log();
|
|
2744
2862
|
p3.log.error(pc3.red("The GitHub CLI (gh) is required for this command."));
|
|
2745
2863
|
p3.log.info("Install it from: https://cli.github.com/");
|
|
@@ -2752,18 +2870,18 @@ async function runSetupProtection(targetDir = process.cwd()) {
|
|
|
2752
2870
|
);
|
|
2753
2871
|
process.exit(1);
|
|
2754
2872
|
}
|
|
2755
|
-
|
|
2756
|
-
|
|
2873
|
+
spinner5.stop("GitHub CLI ready");
|
|
2874
|
+
spinner5.start("Getting repository info...");
|
|
2757
2875
|
const repoInfo = await getGitHubRepoInfo(targetDir);
|
|
2758
2876
|
if (!repoInfo) {
|
|
2759
|
-
|
|
2877
|
+
spinner5.stop("Could not determine repository");
|
|
2760
2878
|
p3.log.error(
|
|
2761
2879
|
pc3.red("Could not determine the GitHub repository for this directory.")
|
|
2762
2880
|
);
|
|
2763
2881
|
p3.log.info("Make sure you're in a git repository with a GitHub remote.");
|
|
2764
2882
|
process.exit(1);
|
|
2765
2883
|
}
|
|
2766
|
-
|
|
2884
|
+
spinner5.stop(`Repository: ${pc3.cyan(`${repoInfo.owner}/${repoInfo.repo}`)}`);
|
|
2767
2885
|
const branches = await p3.multiselect({
|
|
2768
2886
|
message: "Which branches need protection?",
|
|
2769
2887
|
options: [
|
|
@@ -2852,13 +2970,13 @@ async function runSetupProtection(targetDir = process.cwd()) {
|
|
|
2852
2970
|
p3.cancel("Setup cancelled.");
|
|
2853
2971
|
process.exit(0);
|
|
2854
2972
|
}
|
|
2855
|
-
|
|
2973
|
+
spinner5.start("Configuring merge strategy...");
|
|
2856
2974
|
try {
|
|
2857
2975
|
const repoSettings = getMergeStrategySettings(mergeStrategy);
|
|
2858
2976
|
await applyMergeStrategy(repoInfo.owner, repoInfo.repo, repoSettings);
|
|
2859
|
-
|
|
2977
|
+
spinner5.stop("Merge strategy configured!");
|
|
2860
2978
|
} catch (error) {
|
|
2861
|
-
|
|
2979
|
+
spinner5.stop("Failed to configure merge strategy");
|
|
2862
2980
|
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
2863
2981
|
p3.log.warn(pc3.yellow(`Warning: Could not set merge strategy: ${errorMsg}`));
|
|
2864
2982
|
p3.log.info(pc3.dim("Continuing with branch protection..."));
|
|
@@ -2866,16 +2984,16 @@ async function runSetupProtection(targetDir = process.cwd()) {
|
|
|
2866
2984
|
const protectedBranches = [];
|
|
2867
2985
|
const failedBranches = [];
|
|
2868
2986
|
for (const branch of branches) {
|
|
2869
|
-
|
|
2987
|
+
spinner5.start(`Protecting branch: ${branch}...`);
|
|
2870
2988
|
try {
|
|
2871
2989
|
const settings = getDefaultSettings(branch);
|
|
2872
2990
|
settings.requiredReviews = requiredReviews;
|
|
2873
2991
|
await applyBranchProtection(repoInfo.owner, repoInfo.repo, settings);
|
|
2874
2992
|
protectedBranches.push(branch);
|
|
2875
|
-
|
|
2993
|
+
spinner5.stop(`Protected: ${pc3.green(branch)}`);
|
|
2876
2994
|
} catch (error) {
|
|
2877
2995
|
failedBranches.push(branch);
|
|
2878
|
-
|
|
2996
|
+
spinner5.stop(`Failed: ${pc3.red(branch)}`);
|
|
2879
2997
|
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
2880
2998
|
p3.log.warn(
|
|
2881
2999
|
pc3.yellow(
|
|
@@ -3398,8 +3516,8 @@ async function runMetrics(targetDir, options = {}) {
|
|
|
3398
3516
|
selectedDays = daysOption;
|
|
3399
3517
|
}
|
|
3400
3518
|
const analyzeDays = selectedDays || 30;
|
|
3401
|
-
const
|
|
3402
|
-
|
|
3519
|
+
const spinner5 = ciMode ? null : p4.spinner();
|
|
3520
|
+
spinner5?.start("Analyzing repository...");
|
|
3403
3521
|
let overallCompliance = 100;
|
|
3404
3522
|
const complianceScores = [];
|
|
3405
3523
|
if (showGit) {
|
|
@@ -3420,7 +3538,7 @@ async function runMetrics(targetDir, options = {}) {
|
|
|
3420
3538
|
conventionalCompliance,
|
|
3421
3539
|
branchMetrics.branchCompliance
|
|
3422
3540
|
);
|
|
3423
|
-
|
|
3541
|
+
spinner5?.stop("Git analysis complete");
|
|
3424
3542
|
if (ciMode) {
|
|
3425
3543
|
console.log("\n=== GIT METRICS ===");
|
|
3426
3544
|
console.log(`Commits (last ${analyzeDays} days): ${totalCommits}`);
|
|
@@ -3478,13 +3596,13 @@ ${pc4.bold("Branches")}
|
|
|
3478
3596
|
}
|
|
3479
3597
|
if (showCode) {
|
|
3480
3598
|
if (!ciMode && showGit) {
|
|
3481
|
-
|
|
3599
|
+
spinner5?.start("Analyzing codebase...");
|
|
3482
3600
|
} else if (!ciMode) {
|
|
3483
|
-
|
|
3601
|
+
spinner5?.start("Analyzing codebase...");
|
|
3484
3602
|
}
|
|
3485
3603
|
const codebaseMetrics = await analyzeCodebase(targetDir);
|
|
3486
3604
|
complianceScores.push(codebaseMetrics.overallCompliance);
|
|
3487
|
-
|
|
3605
|
+
spinner5?.stop("Codebase analysis complete");
|
|
3488
3606
|
if (ciMode) {
|
|
3489
3607
|
console.log("\n=== CODEBASE METRICS ===");
|
|
3490
3608
|
console.log(`Files analyzed: ${codebaseMetrics.filesAnalyzed}`);
|
|
@@ -3528,10 +3646,60 @@ PASSED: Compliance meets threshold`);
|
|
|
3528
3646
|
}
|
|
3529
3647
|
}
|
|
3530
3648
|
|
|
3649
|
+
// src/commands/install-commands.ts
|
|
3650
|
+
import * as p5 from "@clack/prompts";
|
|
3651
|
+
import pc5 from "picocolors";
|
|
3652
|
+
async function runInstallCommands(targetDir = process.cwd()) {
|
|
3653
|
+
p5.intro(pc5.cyan("RaftStack: Install Claude Code commands and skills"));
|
|
3654
|
+
const spinner5 = p5.spinner();
|
|
3655
|
+
spinner5.start("Installing Claude Code commands and skills...");
|
|
3656
|
+
try {
|
|
3657
|
+
const commandsResult = await generateClaudeCommands(targetDir);
|
|
3658
|
+
const skillsResult = await generateClaudeSkills(targetDir);
|
|
3659
|
+
spinner5.stop("Claude Code commands and skills installed!");
|
|
3660
|
+
const created = [...commandsResult.created, ...skillsResult.created];
|
|
3661
|
+
const backedUp = [...commandsResult.backedUp, ...skillsResult.backedUp];
|
|
3662
|
+
console.log();
|
|
3663
|
+
if (created.length > 0) {
|
|
3664
|
+
p5.log.success(pc5.green("Installed files:"));
|
|
3665
|
+
for (const file of created) {
|
|
3666
|
+
console.log(` ${pc5.dim("+")} ${file}`);
|
|
3667
|
+
}
|
|
3668
|
+
}
|
|
3669
|
+
if (backedUp.length > 0) {
|
|
3670
|
+
console.log();
|
|
3671
|
+
p5.log.info(pc5.dim("Backed up existing files:"));
|
|
3672
|
+
for (const file of backedUp) {
|
|
3673
|
+
console.log(` ${pc5.dim("\u2192")} ${file}.backup`);
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3676
|
+
console.log();
|
|
3677
|
+
p5.note(
|
|
3678
|
+
[
|
|
3679
|
+
`${pc5.cyan("/raftstack/init-context")} - Analyze codebase, generate constitution`,
|
|
3680
|
+
`${pc5.cyan("/raftstack/shape")} - Plan features with adaptive depth`,
|
|
3681
|
+
`${pc5.cyan("/raftstack/discover")} - Extract patterns into standards`,
|
|
3682
|
+
`${pc5.cyan("/raftstack/inject")} - Surface relevant context for tasks`,
|
|
3683
|
+
`${pc5.cyan("/raftstack/index")} - Maintain standards registry`
|
|
3684
|
+
].join("\n"),
|
|
3685
|
+
"Available Commands"
|
|
3686
|
+
);
|
|
3687
|
+
p5.outro(pc5.green("Ready to use! Try /raftstack/init-context to get started."));
|
|
3688
|
+
} catch (error) {
|
|
3689
|
+
spinner5.stop("Error installing commands");
|
|
3690
|
+
p5.log.error(
|
|
3691
|
+
pc5.red(
|
|
3692
|
+
`Error: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
3693
|
+
)
|
|
3694
|
+
);
|
|
3695
|
+
process.exit(1);
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3698
|
+
|
|
3531
3699
|
// package.json
|
|
3532
3700
|
var package_default = {
|
|
3533
3701
|
name: "@raftlabs/raftstack",
|
|
3534
|
-
version: "1.
|
|
3702
|
+
version: "1.9.2",
|
|
3535
3703
|
description: "CLI tool for setting up Git hooks, commit conventions, and GitHub integration",
|
|
3536
3704
|
type: "module",
|
|
3537
3705
|
main: "./dist/index.js",
|
|
@@ -3548,7 +3716,10 @@ var package_default = {
|
|
|
3548
3716
|
files: [
|
|
3549
3717
|
"dist",
|
|
3550
3718
|
"templates",
|
|
3551
|
-
".claude/skills"
|
|
3719
|
+
".claude/skills",
|
|
3720
|
+
".claude/commands",
|
|
3721
|
+
".claude/subagents",
|
|
3722
|
+
".claude/settings.json"
|
|
3552
3723
|
],
|
|
3553
3724
|
scripts: {
|
|
3554
3725
|
build: "tsup",
|
|
@@ -3636,5 +3807,8 @@ program.command("metrics").description("Analyze repository compliance with RaftS
|
|
|
3636
3807
|
});
|
|
3637
3808
|
}
|
|
3638
3809
|
);
|
|
3810
|
+
program.command("install-commands").description("Install or update Claude Code commands and skills").action(async () => {
|
|
3811
|
+
await runInstallCommands(process.cwd());
|
|
3812
|
+
});
|
|
3639
3813
|
program.parse();
|
|
3640
3814
|
//# sourceMappingURL=cli.js.map
|