rulesync 8.12.0 → 8.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-643VJ2QM.js → chunk-RLRAG4LZ.js} +1586 -1418
- package/dist/cli/index.cjs +1708 -1505
- package/dist/cli/index.js +142 -107
- package/dist/index.cjs +1465 -1298
- package/dist/index.d.cts +25 -11
- package/dist/index.d.ts +25 -11
- package/dist/index.js +4 -5
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -79,7 +79,7 @@ import {
|
|
|
79
79
|
stringifyFrontmatter,
|
|
80
80
|
toPosixPath,
|
|
81
81
|
writeFileContent
|
|
82
|
-
} from "../chunk-
|
|
82
|
+
} from "../chunk-RLRAG4LZ.js";
|
|
83
83
|
|
|
84
84
|
// src/cli/index.ts
|
|
85
85
|
import { Command } from "commander";
|
|
@@ -658,32 +658,32 @@ async function convertFetchedFilesToRulesync(params) {
|
|
|
658
658
|
{
|
|
659
659
|
feature: "rules",
|
|
660
660
|
getTargets: () => RulesProcessor.getToolTargets({ global: false }),
|
|
661
|
-
createProcessor: () => new RulesProcessor({
|
|
661
|
+
createProcessor: () => new RulesProcessor({ outputRoot: tempDir, toolTarget: target, global: false, logger: logger5 })
|
|
662
662
|
},
|
|
663
663
|
{
|
|
664
664
|
feature: "commands",
|
|
665
665
|
getTargets: () => CommandsProcessor.getToolTargets({ global: false, includeSimulated: false }),
|
|
666
|
-
createProcessor: () => new CommandsProcessor({
|
|
666
|
+
createProcessor: () => new CommandsProcessor({ outputRoot: tempDir, toolTarget: target, global: false, logger: logger5 })
|
|
667
667
|
},
|
|
668
668
|
{
|
|
669
669
|
feature: "subagents",
|
|
670
670
|
getTargets: () => SubagentsProcessor.getToolTargets({ global: false, includeSimulated: false }),
|
|
671
|
-
createProcessor: () => new SubagentsProcessor({
|
|
671
|
+
createProcessor: () => new SubagentsProcessor({ outputRoot: tempDir, toolTarget: target, global: false, logger: logger5 })
|
|
672
672
|
},
|
|
673
673
|
{
|
|
674
674
|
feature: "ignore",
|
|
675
675
|
getTargets: () => IgnoreProcessor.getToolTargets(),
|
|
676
|
-
createProcessor: () => new IgnoreProcessor({
|
|
676
|
+
createProcessor: () => new IgnoreProcessor({ outputRoot: tempDir, toolTarget: target, logger: logger5 })
|
|
677
677
|
},
|
|
678
678
|
{
|
|
679
679
|
feature: "mcp",
|
|
680
680
|
getTargets: () => McpProcessor.getToolTargets({ global: false }),
|
|
681
|
-
createProcessor: () => new McpProcessor({
|
|
681
|
+
createProcessor: () => new McpProcessor({ outputRoot: tempDir, toolTarget: target, global: false, logger: logger5 })
|
|
682
682
|
},
|
|
683
683
|
{
|
|
684
684
|
feature: "hooks",
|
|
685
685
|
getTargets: () => HooksProcessor.getToolTargets({ global: false }),
|
|
686
|
-
createProcessor: () => new HooksProcessor({
|
|
686
|
+
createProcessor: () => new HooksProcessor({ outputRoot: tempDir, toolTarget: target, global: false, logger: logger5 })
|
|
687
687
|
}
|
|
688
688
|
];
|
|
689
689
|
for (const config of featureConfigs) {
|
|
@@ -728,7 +728,7 @@ function isNotFoundError(error) {
|
|
|
728
728
|
return false;
|
|
729
729
|
}
|
|
730
730
|
async function fetchFiles(params) {
|
|
731
|
-
const { source, options = {},
|
|
731
|
+
const { source, options = {}, outputRoot = process.cwd(), logger: logger5 } = params;
|
|
732
732
|
const parsed = parseSource(source);
|
|
733
733
|
if (parsed.provider === "gitlab") {
|
|
734
734
|
throw new Error(
|
|
@@ -743,7 +743,7 @@ async function fetchFiles(params) {
|
|
|
743
743
|
const target = options.target ?? "rulesync";
|
|
744
744
|
checkPathTraversal({
|
|
745
745
|
relativePath: outputDir,
|
|
746
|
-
intendedRootDir:
|
|
746
|
+
intendedRootDir: outputRoot
|
|
747
747
|
});
|
|
748
748
|
const token = GitHubClient.resolveToken(options.token);
|
|
749
749
|
const client = new GitHubClient({ token });
|
|
@@ -766,7 +766,7 @@ async function fetchFiles(params) {
|
|
|
766
766
|
enabledFeatures,
|
|
767
767
|
target,
|
|
768
768
|
outputDir,
|
|
769
|
-
|
|
769
|
+
outputRoot,
|
|
770
770
|
conflictStrategy,
|
|
771
771
|
logger: logger5
|
|
772
772
|
});
|
|
@@ -793,7 +793,7 @@ async function fetchFiles(params) {
|
|
|
793
793
|
skipped: 0
|
|
794
794
|
};
|
|
795
795
|
}
|
|
796
|
-
const outputBasePath = join(
|
|
796
|
+
const outputBasePath = join(outputRoot, outputDir);
|
|
797
797
|
for (const { relativePath, size } of filesToFetch) {
|
|
798
798
|
checkPathTraversal({
|
|
799
799
|
relativePath,
|
|
@@ -907,7 +907,7 @@ async function fetchAndConvertToolFiles(params) {
|
|
|
907
907
|
enabledFeatures,
|
|
908
908
|
target,
|
|
909
909
|
outputDir,
|
|
910
|
-
|
|
910
|
+
outputRoot,
|
|
911
911
|
conflictStrategy: _conflictStrategy,
|
|
912
912
|
logger: logger5
|
|
913
913
|
} = params;
|
|
@@ -956,7 +956,7 @@ async function fetchAndConvertToolFiles(params) {
|
|
|
956
956
|
logger5.debug(`Fetched to temp: ${toolRelativePath}`);
|
|
957
957
|
})
|
|
958
958
|
);
|
|
959
|
-
const outputBasePath = join(
|
|
959
|
+
const outputBasePath = join(outputRoot, outputDir);
|
|
960
960
|
const { converted, convertedPaths } = await convertFetchedFilesToRulesync({
|
|
961
961
|
tempDir,
|
|
962
962
|
outputDir: outputBasePath,
|
|
@@ -1110,6 +1110,15 @@ async function fetchCommand(logger5, options) {
|
|
|
1110
1110
|
}
|
|
1111
1111
|
|
|
1112
1112
|
// src/cli/commands/generate.ts
|
|
1113
|
+
function sameDirSets(a, b) {
|
|
1114
|
+
const aSet = new Set(a);
|
|
1115
|
+
const bSet = new Set(b);
|
|
1116
|
+
if (aSet.size !== bSet.size) return false;
|
|
1117
|
+
for (const v of aSet) {
|
|
1118
|
+
if (!bSet.has(v)) return false;
|
|
1119
|
+
}
|
|
1120
|
+
return true;
|
|
1121
|
+
}
|
|
1113
1122
|
function logFeatureResult(logger5, params) {
|
|
1114
1123
|
const { count, paths, featureName, isPreview, modePrefix } = params;
|
|
1115
1124
|
if (count > 0) {
|
|
@@ -1124,18 +1133,33 @@ function logFeatureResult(logger5, params) {
|
|
|
1124
1133
|
}
|
|
1125
1134
|
}
|
|
1126
1135
|
async function generateCommand(logger5, options) {
|
|
1127
|
-
const
|
|
1136
|
+
const { baseDir, outputRoots, ...rest } = options;
|
|
1137
|
+
if (baseDir !== void 0) {
|
|
1138
|
+
logger5.warn(
|
|
1139
|
+
"--base-dir is deprecated; use --output-roots instead. It will be removed in a future major release."
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
const outputRootsResolved = outputRoots !== void 0 && outputRoots.length > 0 ? outputRoots : baseDir;
|
|
1143
|
+
if (baseDir !== void 0 && outputRoots !== void 0 && baseDir.length > 0 && outputRoots.length > 0 && !sameDirSets(outputRoots, baseDir)) {
|
|
1144
|
+
logger5.warn(
|
|
1145
|
+
`Both '--output-roots' and '--base-dir' were provided with differing values; using '--output-roots' (${JSON.stringify(outputRoots)}) and ignoring '--base-dir' (${JSON.stringify(baseDir)}).`
|
|
1146
|
+
);
|
|
1147
|
+
}
|
|
1148
|
+
const config = await ConfigResolver.resolve(
|
|
1149
|
+
{ ...rest, outputRoots: outputRootsResolved },
|
|
1150
|
+
{ logger: logger5 }
|
|
1151
|
+
);
|
|
1128
1152
|
const check = config.getCheck();
|
|
1129
1153
|
const isPreview = config.isPreviewMode();
|
|
1130
1154
|
const modePrefix = isPreview ? "[DRY RUN]" : "";
|
|
1131
1155
|
logger5.debug("Generating files...");
|
|
1132
|
-
if (!await checkRulesyncDirExists({
|
|
1156
|
+
if (!await checkRulesyncDirExists({ inputRoot: config.getInputRoot() })) {
|
|
1133
1157
|
throw new CLIError(
|
|
1134
1158
|
".rulesync directory not found. Run 'rulesync init' first.",
|
|
1135
1159
|
ErrorCodes.RULESYNC_DIR_NOT_FOUND
|
|
1136
1160
|
);
|
|
1137
1161
|
}
|
|
1138
|
-
logger5.debug(`
|
|
1162
|
+
logger5.debug(`Output roots: ${config.getOutputRoots().join(", ")}`);
|
|
1139
1163
|
const features = config.getFeatures();
|
|
1140
1164
|
if (features.includes("ignore")) {
|
|
1141
1165
|
logger5.debug("Generating ignore files...");
|
|
@@ -1747,7 +1771,7 @@ async function importCommand(logger5, options) {
|
|
|
1747
1771
|
if (options.targets.length > 1) {
|
|
1748
1772
|
throw new CLIError("Only one tool can be imported at a time", ErrorCodes.IMPORT_FAILED);
|
|
1749
1773
|
}
|
|
1750
|
-
const config = await ConfigResolver.resolve(options);
|
|
1774
|
+
const config = await ConfigResolver.resolve(options, { logger: logger5 });
|
|
1751
1775
|
const tool = config.getTargets()[0];
|
|
1752
1776
|
logger5.debug(`Importing files from ${tool}...`);
|
|
1753
1777
|
const result = await importFromTool({ config, tool, logger: logger5 });
|
|
@@ -1805,7 +1829,7 @@ async function createConfigFile() {
|
|
|
1805
1829
|
$schema: RULESYNC_CONFIG_SCHEMA_URL,
|
|
1806
1830
|
targets: ["copilot", "cursor", "claudecode", "codexcli"],
|
|
1807
1831
|
features: ["rules", "ignore", "mcp", "commands", "subagents", "skills", "hooks"],
|
|
1808
|
-
|
|
1832
|
+
outputRoots: ["."],
|
|
1809
1833
|
delete: true,
|
|
1810
1834
|
verbose: false,
|
|
1811
1835
|
silent: false,
|
|
@@ -2087,8 +2111,8 @@ var ApmLockSchema = z4.looseObject({
|
|
|
2087
2111
|
dependencies: z4.array(ApmLockDependencySchema),
|
|
2088
2112
|
mcp_servers: optional(z4.array(z4.string()))
|
|
2089
2113
|
});
|
|
2090
|
-
function getApmLockPath(
|
|
2091
|
-
return join4(
|
|
2114
|
+
function getApmLockPath(projectRoot) {
|
|
2115
|
+
return join4(projectRoot, APM_LOCKFILE_FILE_NAME);
|
|
2092
2116
|
}
|
|
2093
2117
|
function createEmptyApmLock(params) {
|
|
2094
2118
|
const base = params.existingLock ? { ...params.existingLock } : {};
|
|
@@ -2121,8 +2145,8 @@ ${issues}`);
|
|
|
2121
2145
|
}
|
|
2122
2146
|
return parsed.data;
|
|
2123
2147
|
}
|
|
2124
|
-
async function readApmLock(
|
|
2125
|
-
const path2 = getApmLockPath(
|
|
2148
|
+
async function readApmLock(projectRoot) {
|
|
2149
|
+
const path2 = getApmLockPath(projectRoot);
|
|
2126
2150
|
if (!await fileExists(path2)) {
|
|
2127
2151
|
return null;
|
|
2128
2152
|
}
|
|
@@ -2130,7 +2154,7 @@ async function readApmLock(baseDir) {
|
|
|
2130
2154
|
return parseApmLock(content);
|
|
2131
2155
|
}
|
|
2132
2156
|
async function writeApmLock(params) {
|
|
2133
|
-
const path2 = getApmLockPath(params.
|
|
2157
|
+
const path2 = getApmLockPath(params.projectRoot);
|
|
2134
2158
|
const content = serializeApmLock(params.lock);
|
|
2135
2159
|
await writeFileContent(path2, content);
|
|
2136
2160
|
}
|
|
@@ -2164,11 +2188,11 @@ var ApmManifestSchema = z5.looseObject({
|
|
|
2164
2188
|
})
|
|
2165
2189
|
)
|
|
2166
2190
|
});
|
|
2167
|
-
function getApmManifestPath(
|
|
2168
|
-
return join5(
|
|
2191
|
+
function getApmManifestPath(projectRoot) {
|
|
2192
|
+
return join5(projectRoot, APM_MANIFEST_FILE_NAME);
|
|
2169
2193
|
}
|
|
2170
|
-
async function apmManifestExists(
|
|
2171
|
-
return fileExists(getApmManifestPath(
|
|
2194
|
+
async function apmManifestExists(projectRoot) {
|
|
2195
|
+
return fileExists(getApmManifestPath(projectRoot));
|
|
2172
2196
|
}
|
|
2173
2197
|
function parseApmManifest(content) {
|
|
2174
2198
|
const loaded = load2(content);
|
|
@@ -2190,8 +2214,8 @@ function parseApmManifest(content) {
|
|
|
2190
2214
|
dependencies
|
|
2191
2215
|
};
|
|
2192
2216
|
}
|
|
2193
|
-
async function readApmManifest(
|
|
2194
|
-
const path2 = getApmManifestPath(
|
|
2217
|
+
async function readApmManifest(projectRoot) {
|
|
2218
|
+
const path2 = getApmManifestPath(projectRoot);
|
|
2195
2219
|
const content = await readFileContent(path2);
|
|
2196
2220
|
return parseApmManifest(content);
|
|
2197
2221
|
}
|
|
@@ -2344,13 +2368,13 @@ var APM_PRIMITIVES = [
|
|
|
2344
2368
|
}
|
|
2345
2369
|
];
|
|
2346
2370
|
async function installApm(params) {
|
|
2347
|
-
const {
|
|
2348
|
-
const manifest = await readApmManifest(
|
|
2371
|
+
const { projectRoot, options = {}, logger: logger5 } = params;
|
|
2372
|
+
const manifest = await readApmManifest(projectRoot);
|
|
2349
2373
|
if (manifest.dependencies.length === 0) {
|
|
2350
2374
|
logger5.warn("apm.yml has no dependencies.apm entries. Nothing to install.");
|
|
2351
2375
|
return { dependenciesProcessed: 0, deployedFileCount: 0, failedDependencyCount: 0 };
|
|
2352
2376
|
}
|
|
2353
|
-
const existingLock = await readApmLock(
|
|
2377
|
+
const existingLock = await readApmLock(projectRoot);
|
|
2354
2378
|
if (options.frozen) {
|
|
2355
2379
|
if (!existingLock) {
|
|
2356
2380
|
throw new Error(
|
|
@@ -2394,7 +2418,7 @@ async function installApm(params) {
|
|
|
2394
2418
|
dep,
|
|
2395
2419
|
client,
|
|
2396
2420
|
semaphore,
|
|
2397
|
-
|
|
2421
|
+
projectRoot,
|
|
2398
2422
|
existingLock,
|
|
2399
2423
|
frozen,
|
|
2400
2424
|
update: options.update ?? false,
|
|
@@ -2449,19 +2473,19 @@ async function installApm(params) {
|
|
|
2449
2473
|
continue;
|
|
2450
2474
|
}
|
|
2451
2475
|
try {
|
|
2452
|
-
checkPathTraversal({ relativePath, intendedRootDir:
|
|
2476
|
+
checkPathTraversal({ relativePath, intendedRootDir: projectRoot });
|
|
2453
2477
|
} catch {
|
|
2454
|
-
logger5.warn(`Refusing to remove stale apm file outside
|
|
2478
|
+
logger5.warn(`Refusing to remove stale apm file outside projectRoot: "${relativePath}".`);
|
|
2455
2479
|
continue;
|
|
2456
2480
|
}
|
|
2457
|
-
const absolute = join6(
|
|
2481
|
+
const absolute = join6(projectRoot, relativePath);
|
|
2458
2482
|
await removeFile(absolute);
|
|
2459
2483
|
logger5.debug(`Removed stale apm file: ${relativePath}`);
|
|
2460
2484
|
}
|
|
2461
2485
|
}
|
|
2462
2486
|
if (!frozen) {
|
|
2463
2487
|
newLock.generated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
2464
|
-
await writeApmLock({
|
|
2488
|
+
await writeApmLock({ projectRoot, lock: newLock });
|
|
2465
2489
|
if (failedCount === 0) {
|
|
2466
2490
|
logger5.debug("rulesync-apm.lock.yaml updated.");
|
|
2467
2491
|
} else {
|
|
@@ -2477,7 +2501,7 @@ async function installApm(params) {
|
|
|
2477
2501
|
};
|
|
2478
2502
|
}
|
|
2479
2503
|
async function installDependency(params) {
|
|
2480
|
-
const { dep, client, semaphore,
|
|
2504
|
+
const { dep, client, semaphore, projectRoot, existingLock, frozen, update, logger: logger5 } = params;
|
|
2481
2505
|
const repoUrl = canonicalRepoUrl(dep);
|
|
2482
2506
|
const locked = existingLock ? findApmLockDependency(existingLock, repoUrl) : void 0;
|
|
2483
2507
|
let resolvedRef;
|
|
@@ -2521,7 +2545,7 @@ async function installDependency(params) {
|
|
|
2521
2545
|
const deployRelative = toPosixPath(join6(primitive.deployDir, relativeToBase));
|
|
2522
2546
|
checkPathTraversal({
|
|
2523
2547
|
relativePath: deployRelative,
|
|
2524
|
-
intendedRootDir:
|
|
2548
|
+
intendedRootDir: projectRoot
|
|
2525
2549
|
});
|
|
2526
2550
|
const content = await withSemaphore(
|
|
2527
2551
|
semaphore,
|
|
@@ -2536,7 +2560,7 @@ async function installDependency(params) {
|
|
|
2536
2560
|
}
|
|
2537
2561
|
deployed.push({ path: deployRelative, content });
|
|
2538
2562
|
if (!frozen) {
|
|
2539
|
-
await writeFileContent(join6(
|
|
2563
|
+
await writeFileContent(join6(projectRoot, deployRelative), content);
|
|
2540
2564
|
}
|
|
2541
2565
|
}
|
|
2542
2566
|
}
|
|
@@ -2558,7 +2582,7 @@ async function installDependency(params) {
|
|
|
2558
2582
|
}
|
|
2559
2583
|
if (frozen) {
|
|
2560
2584
|
for (const { path: deployRelative, content } of deployed) {
|
|
2561
|
-
await writeFileContent(join6(
|
|
2585
|
+
await writeFileContent(join6(projectRoot, deployRelative), content);
|
|
2562
2586
|
}
|
|
2563
2587
|
}
|
|
2564
2588
|
const lockEntry = {
|
|
@@ -2706,8 +2730,8 @@ var GhLockSchema = z6.looseObject({
|
|
|
2706
2730
|
generated_at: z6.string(),
|
|
2707
2731
|
installations: z6.array(GhLockInstallationSchema)
|
|
2708
2732
|
});
|
|
2709
|
-
function getGhLockPath(
|
|
2710
|
-
return join7(
|
|
2733
|
+
function getGhLockPath(projectRoot) {
|
|
2734
|
+
return join7(projectRoot, GH_LOCKFILE_FILE_NAME);
|
|
2711
2735
|
}
|
|
2712
2736
|
function createEmptyGhLock(params) {
|
|
2713
2737
|
const base = params?.existingLock ? { ...params.existingLock } : {};
|
|
@@ -2739,8 +2763,8 @@ ${issues}`);
|
|
|
2739
2763
|
}
|
|
2740
2764
|
return parsed.data;
|
|
2741
2765
|
}
|
|
2742
|
-
async function readGhLock(
|
|
2743
|
-
const path2 = getGhLockPath(
|
|
2766
|
+
async function readGhLock(projectRoot) {
|
|
2767
|
+
const path2 = getGhLockPath(projectRoot);
|
|
2744
2768
|
if (!await fileExists(path2)) {
|
|
2745
2769
|
return null;
|
|
2746
2770
|
}
|
|
@@ -2748,7 +2772,7 @@ async function readGhLock(baseDir) {
|
|
|
2748
2772
|
return parseGhLock(content);
|
|
2749
2773
|
}
|
|
2750
2774
|
async function writeGhLock(params) {
|
|
2751
|
-
const path2 = getGhLockPath(params.
|
|
2775
|
+
const path2 = getGhLockPath(params.projectRoot);
|
|
2752
2776
|
const content = serializeGhLock(params.lock);
|
|
2753
2777
|
await writeFileContent(path2, content);
|
|
2754
2778
|
}
|
|
@@ -2800,7 +2824,7 @@ function relativeInstallDirFor(params) {
|
|
|
2800
2824
|
var SKILLS_REMOTE_DIR = "skills";
|
|
2801
2825
|
var SKILL_FILE_NAME2 = "SKILL.md";
|
|
2802
2826
|
async function installGh(params) {
|
|
2803
|
-
const {
|
|
2827
|
+
const { projectRoot, sources, options = {}, logger: logger5 } = params;
|
|
2804
2828
|
if (sources.length === 0) {
|
|
2805
2829
|
return { sourcesProcessed: 0, installedSkillCount: 0, failedSourceCount: 0 };
|
|
2806
2830
|
}
|
|
@@ -2837,7 +2861,7 @@ async function installGh(params) {
|
|
|
2837
2861
|
scope
|
|
2838
2862
|
};
|
|
2839
2863
|
});
|
|
2840
|
-
const existingLock = await readGhLock(
|
|
2864
|
+
const existingLock = await readGhLock(projectRoot);
|
|
2841
2865
|
const frozen = options.frozen ?? false;
|
|
2842
2866
|
const update = options.update ?? false;
|
|
2843
2867
|
if (frozen && !existingLock) {
|
|
@@ -2888,7 +2912,7 @@ async function installGh(params) {
|
|
|
2888
2912
|
rs,
|
|
2889
2913
|
client,
|
|
2890
2914
|
semaphore,
|
|
2891
|
-
|
|
2915
|
+
projectRoot,
|
|
2892
2916
|
existingLock,
|
|
2893
2917
|
frozen,
|
|
2894
2918
|
update,
|
|
@@ -2951,7 +2975,7 @@ async function installGh(params) {
|
|
|
2951
2975
|
await removeStaleFile({
|
|
2952
2976
|
relativePath: deployed,
|
|
2953
2977
|
scope: prev.scope === "user" ? "user" : "project",
|
|
2954
|
-
|
|
2978
|
+
projectRoot,
|
|
2955
2979
|
logger: logger5
|
|
2956
2980
|
});
|
|
2957
2981
|
}
|
|
@@ -2959,7 +2983,7 @@ async function installGh(params) {
|
|
|
2959
2983
|
}
|
|
2960
2984
|
if (!frozen) {
|
|
2961
2985
|
newLock.generated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
2962
|
-
await writeGhLock({
|
|
2986
|
+
await writeGhLock({ projectRoot, lock: newLock });
|
|
2963
2987
|
if (failedCount === 0) {
|
|
2964
2988
|
logger5.debug("rulesync-gh.lock.yaml updated.");
|
|
2965
2989
|
} else {
|
|
@@ -2975,7 +2999,7 @@ async function installGh(params) {
|
|
|
2975
2999
|
};
|
|
2976
3000
|
}
|
|
2977
3001
|
async function installSource(params) {
|
|
2978
|
-
const { rs, client, semaphore,
|
|
3002
|
+
const { rs, client, semaphore, projectRoot, existingLock, frozen, update, logger: logger5 } = params;
|
|
2979
3003
|
const { entry, owner, repo, agent, scope } = rs;
|
|
2980
3004
|
const sourceKey = entry.source;
|
|
2981
3005
|
let resolvedRef;
|
|
@@ -3050,7 +3074,7 @@ async function installSource(params) {
|
|
|
3050
3074
|
}
|
|
3051
3075
|
const results = [];
|
|
3052
3076
|
const installRelDir = relativeInstallDirFor({ agent, scope });
|
|
3053
|
-
const scopeRoot = scope === "user" ? getHomeDirectory() :
|
|
3077
|
+
const scopeRoot = scope === "user" ? getHomeDirectory() : projectRoot;
|
|
3054
3078
|
const sourceUrl = `https://github.com/${owner}/${repo}`;
|
|
3055
3079
|
const repository = `${owner}/${repo}`;
|
|
3056
3080
|
const provenanceRef = usedTag ? resolvedRef : resolvedSha;
|
|
@@ -3166,12 +3190,12 @@ ${content}`;
|
|
|
3166
3190
|
return results;
|
|
3167
3191
|
}
|
|
3168
3192
|
async function removeStaleFile(params) {
|
|
3169
|
-
const { relativePath, scope,
|
|
3193
|
+
const { relativePath, scope, projectRoot, logger: logger5 } = params;
|
|
3170
3194
|
if (posix3.isAbsolute(relativePath) || relativePath.split(/[/\\]/).includes("..")) {
|
|
3171
3195
|
logger5.warn(`Refusing to remove stale gh file with suspicious path: "${relativePath}".`);
|
|
3172
3196
|
return;
|
|
3173
3197
|
}
|
|
3174
|
-
const scopeRoot = scope === "user" ? getHomeDirectory() :
|
|
3198
|
+
const scopeRoot = scope === "user" ? getHomeDirectory() : projectRoot;
|
|
3175
3199
|
try {
|
|
3176
3200
|
checkPathTraversal({ relativePath, intendedRootDir: scopeRoot });
|
|
3177
3201
|
} catch {
|
|
@@ -3343,7 +3367,7 @@ async function fetchSkillFiles(params) {
|
|
|
3343
3367
|
var MAX_WALK_DEPTH = 20;
|
|
3344
3368
|
var MAX_TOTAL_FILES = 1e4;
|
|
3345
3369
|
var MAX_TOTAL_SIZE = 100 * 1024 * 1024;
|
|
3346
|
-
async function walkDirectory(dir,
|
|
3370
|
+
async function walkDirectory(dir, outputRoot, depth = 0, ctx = { totalFiles: 0, totalSize: 0 }, logger5) {
|
|
3347
3371
|
if (depth > MAX_WALK_DEPTH) {
|
|
3348
3372
|
throw new GitClientError(
|
|
3349
3373
|
`Directory tree exceeds max depth of ${MAX_WALK_DEPTH}: "${dir}". Aborting to prevent resource exhaustion.`
|
|
@@ -3358,7 +3382,7 @@ async function walkDirectory(dir, baseDir, depth = 0, ctx = { totalFiles: 0, tot
|
|
|
3358
3382
|
continue;
|
|
3359
3383
|
}
|
|
3360
3384
|
if (await directoryExists(fullPath)) {
|
|
3361
|
-
results.push(...await walkDirectory(fullPath,
|
|
3385
|
+
results.push(...await walkDirectory(fullPath, outputRoot, depth + 1, ctx, logger5));
|
|
3362
3386
|
} else {
|
|
3363
3387
|
const size = await getFileSize(fullPath);
|
|
3364
3388
|
if (size > MAX_FILE_SIZE) {
|
|
@@ -3380,7 +3404,7 @@ async function walkDirectory(dir, baseDir, depth = 0, ctx = { totalFiles: 0, tot
|
|
|
3380
3404
|
);
|
|
3381
3405
|
}
|
|
3382
3406
|
const content = await readFileContent(fullPath);
|
|
3383
|
-
results.push({ relativePath: relative(
|
|
3407
|
+
results.push({ relativePath: relative(outputRoot, fullPath), content, size });
|
|
3384
3408
|
}
|
|
3385
3409
|
}
|
|
3386
3410
|
return results;
|
|
@@ -3434,7 +3458,7 @@ function createEmptyLock() {
|
|
|
3434
3458
|
}
|
|
3435
3459
|
async function readLockFile(params) {
|
|
3436
3460
|
const { logger: logger5 } = params;
|
|
3437
|
-
const lockPath = join11(params.
|
|
3461
|
+
const lockPath = join11(params.projectRoot, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH);
|
|
3438
3462
|
if (!await fileExists(lockPath)) {
|
|
3439
3463
|
logger5.debug("No sources lockfile found, starting fresh.");
|
|
3440
3464
|
return createEmptyLock();
|
|
@@ -3463,7 +3487,7 @@ async function readLockFile(params) {
|
|
|
3463
3487
|
}
|
|
3464
3488
|
async function writeLockFile(params) {
|
|
3465
3489
|
const { logger: logger5 } = params;
|
|
3466
|
-
const lockPath = join11(params.
|
|
3490
|
+
const lockPath = join11(params.projectRoot, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH);
|
|
3467
3491
|
const content = JSON.stringify(params.lock, null, 2) + "\n";
|
|
3468
3492
|
await writeFileContent(lockPath, content);
|
|
3469
3493
|
logger5.debug(`Wrote sources lockfile to ${lockPath}`);
|
|
@@ -3538,7 +3562,7 @@ function getLockedSkillNames(entry) {
|
|
|
3538
3562
|
|
|
3539
3563
|
// src/lib/sources.ts
|
|
3540
3564
|
async function resolveAndFetchSources(params) {
|
|
3541
|
-
const { sources,
|
|
3565
|
+
const { sources, projectRoot, options = {}, logger: logger5 } = params;
|
|
3542
3566
|
if (sources.length === 0) {
|
|
3543
3567
|
return { fetchedSkillCount: 0, sourcesProcessed: 0 };
|
|
3544
3568
|
}
|
|
@@ -3546,7 +3570,7 @@ async function resolveAndFetchSources(params) {
|
|
|
3546
3570
|
logger5.info("Skipping source fetching.");
|
|
3547
3571
|
return { fetchedSkillCount: 0, sourcesProcessed: 0 };
|
|
3548
3572
|
}
|
|
3549
|
-
let lock = options.updateSources ? createEmptyLock() : await readLockFile({
|
|
3573
|
+
let lock = options.updateSources ? createEmptyLock() : await readLockFile({ projectRoot, logger: logger5 });
|
|
3550
3574
|
if (options.frozen) {
|
|
3551
3575
|
const missingKeys = [];
|
|
3552
3576
|
for (const source of sources) {
|
|
@@ -3564,7 +3588,7 @@ async function resolveAndFetchSources(params) {
|
|
|
3564
3588
|
const originalLockJson = JSON.stringify(lock);
|
|
3565
3589
|
const token = GitHubClient.resolveToken(options.token);
|
|
3566
3590
|
const client = new GitHubClient({ token });
|
|
3567
|
-
const localSkillNames = await getLocalSkillDirNames(
|
|
3591
|
+
const localSkillNames = await getLocalSkillDirNames(projectRoot);
|
|
3568
3592
|
let totalSkillCount = 0;
|
|
3569
3593
|
const allFetchedSkillNames = /* @__PURE__ */ new Set();
|
|
3570
3594
|
for (const sourceEntry of sources) {
|
|
@@ -3574,7 +3598,7 @@ async function resolveAndFetchSources(params) {
|
|
|
3574
3598
|
if (transport === "git") {
|
|
3575
3599
|
result = await fetchSourceViaGit({
|
|
3576
3600
|
sourceEntry,
|
|
3577
|
-
|
|
3601
|
+
projectRoot,
|
|
3578
3602
|
lock,
|
|
3579
3603
|
localSkillNames,
|
|
3580
3604
|
alreadyFetchedSkillNames: allFetchedSkillNames,
|
|
@@ -3586,7 +3610,7 @@ async function resolveAndFetchSources(params) {
|
|
|
3586
3610
|
result = await fetchSource({
|
|
3587
3611
|
sourceEntry,
|
|
3588
3612
|
client,
|
|
3589
|
-
|
|
3613
|
+
projectRoot,
|
|
3590
3614
|
lock,
|
|
3591
3615
|
localSkillNames,
|
|
3592
3616
|
alreadyFetchedSkillNames: allFetchedSkillNames,
|
|
@@ -3620,7 +3644,7 @@ async function resolveAndFetchSources(params) {
|
|
|
3620
3644
|
}
|
|
3621
3645
|
lock = { lockfileVersion: lock.lockfileVersion, sources: prunedSources };
|
|
3622
3646
|
if (!options.frozen && JSON.stringify(lock) !== originalLockJson) {
|
|
3623
|
-
await writeLockFile({
|
|
3647
|
+
await writeLockFile({ projectRoot, lock, logger: logger5 });
|
|
3624
3648
|
} else {
|
|
3625
3649
|
logger5.debug("Lockfile unchanged, skipping write.");
|
|
3626
3650
|
}
|
|
@@ -3771,7 +3795,7 @@ async function fetchSource(params) {
|
|
|
3771
3795
|
const {
|
|
3772
3796
|
sourceEntry,
|
|
3773
3797
|
client,
|
|
3774
|
-
|
|
3798
|
+
projectRoot,
|
|
3775
3799
|
localSkillNames,
|
|
3776
3800
|
alreadyFetchedSkillNames,
|
|
3777
3801
|
updateSources,
|
|
@@ -3800,7 +3824,7 @@ async function fetchSource(params) {
|
|
|
3800
3824
|
ref = resolvedSha;
|
|
3801
3825
|
logger5.debug(`Resolved ${sourceKey} ref "${requestedRef}" to SHA: ${resolvedSha}`);
|
|
3802
3826
|
}
|
|
3803
|
-
const curatedDir = join12(
|
|
3827
|
+
const curatedDir = join12(projectRoot, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH);
|
|
3804
3828
|
if (locked && resolvedSha === locked.resolvedRef && !updateSources) {
|
|
3805
3829
|
const allExist = await checkLockedSkillsExist(curatedDir, lockedSkillNames);
|
|
3806
3830
|
if (allExist) {
|
|
@@ -3948,7 +3972,7 @@ async function fetchSource(params) {
|
|
|
3948
3972
|
async function fetchSourceViaGit(params) {
|
|
3949
3973
|
const {
|
|
3950
3974
|
sourceEntry,
|
|
3951
|
-
|
|
3975
|
+
projectRoot,
|
|
3952
3976
|
localSkillNames,
|
|
3953
3977
|
alreadyFetchedSkillNames,
|
|
3954
3978
|
updateSources,
|
|
@@ -3975,7 +3999,7 @@ async function fetchSourceViaGit(params) {
|
|
|
3975
3999
|
requestedRef = def.ref;
|
|
3976
4000
|
resolvedSha = def.sha;
|
|
3977
4001
|
}
|
|
3978
|
-
const curatedDir = join12(
|
|
4002
|
+
const curatedDir = join12(projectRoot, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH);
|
|
3979
4003
|
if (locked && resolvedSha === locked.resolvedRef && !updateSources) {
|
|
3980
4004
|
if (await checkLockedSkillsExist(curatedDir, lockedSkillNames)) {
|
|
3981
4005
|
return { skillCount: 0, fetchedSkillNames: lockedSkillNames, updatedLock: lock };
|
|
@@ -4057,8 +4081,8 @@ async function installCommand(logger5, options) {
|
|
|
4057
4081
|
await runRulesyncInstall(logger5, options);
|
|
4058
4082
|
}
|
|
4059
4083
|
async function runRulesyncInstall(logger5, options) {
|
|
4060
|
-
const
|
|
4061
|
-
const apmExists = await apmManifestExists(
|
|
4084
|
+
const projectRoot = process.cwd();
|
|
4085
|
+
const apmExists = await apmManifestExists(projectRoot);
|
|
4062
4086
|
const config = await ConfigResolver.resolve({
|
|
4063
4087
|
configPath: options.configPath,
|
|
4064
4088
|
verbose: options.verbose,
|
|
@@ -4083,7 +4107,7 @@ async function runRulesyncInstall(logger5, options) {
|
|
|
4083
4107
|
logger5.debug(`Installing skills from ${sources.length} source(s)...`);
|
|
4084
4108
|
const result = await resolveAndFetchSources({
|
|
4085
4109
|
sources,
|
|
4086
|
-
|
|
4110
|
+
projectRoot,
|
|
4087
4111
|
options: {
|
|
4088
4112
|
updateSources: options.update,
|
|
4089
4113
|
frozen: options.frozen,
|
|
@@ -4104,14 +4128,14 @@ async function runRulesyncInstall(logger5, options) {
|
|
|
4104
4128
|
}
|
|
4105
4129
|
}
|
|
4106
4130
|
async function runApmInstall(logger5, options) {
|
|
4107
|
-
const
|
|
4108
|
-
if (!await apmManifestExists(
|
|
4131
|
+
const projectRoot = process.cwd();
|
|
4132
|
+
if (!await apmManifestExists(projectRoot)) {
|
|
4109
4133
|
throw new Error(
|
|
4110
4134
|
"--mode apm requires an apm.yml at the project root. Create one or drop --mode apm to fall back to rulesync mode."
|
|
4111
4135
|
);
|
|
4112
4136
|
}
|
|
4113
4137
|
const result = await installApm({
|
|
4114
|
-
|
|
4138
|
+
projectRoot,
|
|
4115
4139
|
options: {
|
|
4116
4140
|
update: options.update,
|
|
4117
4141
|
frozen: options.frozen,
|
|
@@ -4138,7 +4162,7 @@ async function runApmInstall(logger5, options) {
|
|
|
4138
4162
|
}
|
|
4139
4163
|
}
|
|
4140
4164
|
async function runGhInstall(logger5, options) {
|
|
4141
|
-
const
|
|
4165
|
+
const projectRoot = process.cwd();
|
|
4142
4166
|
const config = await ConfigResolver.resolve({
|
|
4143
4167
|
configPath: options.configPath,
|
|
4144
4168
|
verbose: options.verbose,
|
|
@@ -4150,7 +4174,7 @@ async function runGhInstall(logger5, options) {
|
|
|
4150
4174
|
return;
|
|
4151
4175
|
}
|
|
4152
4176
|
const result = await installGh({
|
|
4153
|
-
|
|
4177
|
+
projectRoot,
|
|
4154
4178
|
sources,
|
|
4155
4179
|
options: {
|
|
4156
4180
|
update: options.update,
|
|
@@ -4273,7 +4297,7 @@ async function putCommand({
|
|
|
4273
4297
|
}
|
|
4274
4298
|
const fileContent = stringifyFrontmatter(body, frontmatter);
|
|
4275
4299
|
const command = new RulesyncCommand({
|
|
4276
|
-
|
|
4300
|
+
outputRoot: process.cwd(),
|
|
4277
4301
|
relativeDirPath: RULESYNC_COMMANDS_RELATIVE_DIR_PATH,
|
|
4278
4302
|
relativeFilePath: filename,
|
|
4279
4303
|
frontmatter,
|
|
@@ -4418,7 +4442,7 @@ async function executeConvert(options) {
|
|
|
4418
4442
|
features: options.features ?? ["*"],
|
|
4419
4443
|
global: options.global,
|
|
4420
4444
|
dryRun: options.dryRun,
|
|
4421
|
-
// Always use default
|
|
4445
|
+
// Always use default outputRoots (process.cwd()) and configPath
|
|
4422
4446
|
// verbose and silent are meaningless in MCP context
|
|
4423
4447
|
verbose: false,
|
|
4424
4448
|
silent: true
|
|
@@ -4486,7 +4510,7 @@ var generateOptionsSchema = z10.object({
|
|
|
4486
4510
|
});
|
|
4487
4511
|
async function executeGenerate(options = {}) {
|
|
4488
4512
|
try {
|
|
4489
|
-
const exists = await checkRulesyncDirExists({
|
|
4513
|
+
const exists = await checkRulesyncDirExists({ inputRoot: process.cwd() });
|
|
4490
4514
|
if (!exists) {
|
|
4491
4515
|
return {
|
|
4492
4516
|
success: false,
|
|
@@ -4503,7 +4527,7 @@ async function executeGenerate(options = {}) {
|
|
|
4503
4527
|
simulateCommands: options.simulateCommands,
|
|
4504
4528
|
simulateSubagents: options.simulateSubagents,
|
|
4505
4529
|
simulateSkills: options.simulateSkills,
|
|
4506
|
-
// Always use default
|
|
4530
|
+
// Always use default outputRoots (process.cwd()) and configPath
|
|
4507
4531
|
// verbose and silent are meaningless in MCP context
|
|
4508
4532
|
verbose: false,
|
|
4509
4533
|
silent: true
|
|
@@ -4603,19 +4627,19 @@ async function putHooksFile({ content }) {
|
|
|
4603
4627
|
);
|
|
4604
4628
|
}
|
|
4605
4629
|
try {
|
|
4606
|
-
const
|
|
4630
|
+
const outputRoot = process.cwd();
|
|
4607
4631
|
const paths = RulesyncHooks.getSettablePaths();
|
|
4608
4632
|
const relativeDirPath = paths.relativeDirPath;
|
|
4609
4633
|
const relativeFilePath = paths.relativeFilePath;
|
|
4610
|
-
const fullPath = join14(
|
|
4634
|
+
const fullPath = join14(outputRoot, relativeDirPath, relativeFilePath);
|
|
4611
4635
|
const rulesyncHooks = new RulesyncHooks({
|
|
4612
|
-
|
|
4636
|
+
outputRoot,
|
|
4613
4637
|
relativeDirPath,
|
|
4614
4638
|
relativeFilePath,
|
|
4615
4639
|
fileContent: content,
|
|
4616
4640
|
validate: true
|
|
4617
4641
|
});
|
|
4618
|
-
await ensureDir(join14(
|
|
4642
|
+
await ensureDir(join14(outputRoot, relativeDirPath));
|
|
4619
4643
|
await writeFileContent(fullPath, content);
|
|
4620
4644
|
const relativePathFromCwd = join14(relativeDirPath, relativeFilePath);
|
|
4621
4645
|
return {
|
|
@@ -4633,9 +4657,9 @@ async function putHooksFile({ content }) {
|
|
|
4633
4657
|
}
|
|
4634
4658
|
async function deleteHooksFile() {
|
|
4635
4659
|
try {
|
|
4636
|
-
const
|
|
4660
|
+
const outputRoot = process.cwd();
|
|
4637
4661
|
const paths = RulesyncHooks.getSettablePaths();
|
|
4638
|
-
const filePath = join14(
|
|
4662
|
+
const filePath = join14(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
4639
4663
|
await removeFile(filePath);
|
|
4640
4664
|
const relativePathFromCwd = join14(paths.relativeDirPath, paths.relativeFilePath);
|
|
4641
4665
|
return {
|
|
@@ -4809,7 +4833,7 @@ async function executeImport(options) {
|
|
|
4809
4833
|
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
4810
4834
|
features: options.features,
|
|
4811
4835
|
global: options.global,
|
|
4812
|
-
// Always use default
|
|
4836
|
+
// Always use default outputRoots (process.cwd()) and configPath
|
|
4813
4837
|
// verbose and silent are meaningless in MCP context
|
|
4814
4838
|
verbose: false,
|
|
4815
4839
|
silent: true
|
|
@@ -4906,19 +4930,19 @@ async function putMcpFile({ content }) {
|
|
|
4906
4930
|
);
|
|
4907
4931
|
}
|
|
4908
4932
|
try {
|
|
4909
|
-
const
|
|
4933
|
+
const outputRoot = process.cwd();
|
|
4910
4934
|
const paths = RulesyncMcp.getSettablePaths();
|
|
4911
4935
|
const relativeDirPath = paths.recommended.relativeDirPath;
|
|
4912
4936
|
const relativeFilePath = paths.recommended.relativeFilePath;
|
|
4913
|
-
const fullPath = join16(
|
|
4937
|
+
const fullPath = join16(outputRoot, relativeDirPath, relativeFilePath);
|
|
4914
4938
|
const rulesyncMcp = new RulesyncMcp({
|
|
4915
|
-
|
|
4939
|
+
outputRoot,
|
|
4916
4940
|
relativeDirPath,
|
|
4917
4941
|
relativeFilePath,
|
|
4918
4942
|
fileContent: content,
|
|
4919
4943
|
validate: true
|
|
4920
4944
|
});
|
|
4921
|
-
await ensureDir(join16(
|
|
4945
|
+
await ensureDir(join16(outputRoot, relativeDirPath));
|
|
4922
4946
|
await writeFileContent(fullPath, content);
|
|
4923
4947
|
const relativePathFromCwd = join16(relativeDirPath, relativeFilePath);
|
|
4924
4948
|
return {
|
|
@@ -4936,14 +4960,18 @@ async function putMcpFile({ content }) {
|
|
|
4936
4960
|
}
|
|
4937
4961
|
async function deleteMcpFile() {
|
|
4938
4962
|
try {
|
|
4939
|
-
const
|
|
4963
|
+
const outputRoot = process.cwd();
|
|
4940
4964
|
const paths = RulesyncMcp.getSettablePaths();
|
|
4941
4965
|
const recommendedPath = join16(
|
|
4942
|
-
|
|
4966
|
+
outputRoot,
|
|
4943
4967
|
paths.recommended.relativeDirPath,
|
|
4944
4968
|
paths.recommended.relativeFilePath
|
|
4945
4969
|
);
|
|
4946
|
-
const legacyPath = join16(
|
|
4970
|
+
const legacyPath = join16(
|
|
4971
|
+
outputRoot,
|
|
4972
|
+
paths.legacy.relativeDirPath,
|
|
4973
|
+
paths.legacy.relativeFilePath
|
|
4974
|
+
);
|
|
4947
4975
|
await removeFile(recommendedPath);
|
|
4948
4976
|
await removeFile(legacyPath);
|
|
4949
4977
|
const relativePathFromCwd = join16(
|
|
@@ -5042,19 +5070,19 @@ async function putPermissionsFile({ content }) {
|
|
|
5042
5070
|
);
|
|
5043
5071
|
}
|
|
5044
5072
|
try {
|
|
5045
|
-
const
|
|
5073
|
+
const outputRoot = process.cwd();
|
|
5046
5074
|
const paths = RulesyncPermissions.getSettablePaths();
|
|
5047
5075
|
const relativeDirPath = paths.relativeDirPath;
|
|
5048
5076
|
const relativeFilePath = paths.relativeFilePath;
|
|
5049
|
-
const fullPath = join17(
|
|
5077
|
+
const fullPath = join17(outputRoot, relativeDirPath, relativeFilePath);
|
|
5050
5078
|
const rulesyncPermissions = new RulesyncPermissions({
|
|
5051
|
-
|
|
5079
|
+
outputRoot,
|
|
5052
5080
|
relativeDirPath,
|
|
5053
5081
|
relativeFilePath,
|
|
5054
5082
|
fileContent: content,
|
|
5055
5083
|
validate: true
|
|
5056
5084
|
});
|
|
5057
|
-
await ensureDir(join17(
|
|
5085
|
+
await ensureDir(join17(outputRoot, relativeDirPath));
|
|
5058
5086
|
await writeFileContent(fullPath, content);
|
|
5059
5087
|
const relativePathFromCwd = join17(relativeDirPath, relativeFilePath);
|
|
5060
5088
|
return {
|
|
@@ -5072,9 +5100,9 @@ async function putPermissionsFile({ content }) {
|
|
|
5072
5100
|
}
|
|
5073
5101
|
async function deletePermissionsFile() {
|
|
5074
5102
|
try {
|
|
5075
|
-
const
|
|
5103
|
+
const outputRoot = process.cwd();
|
|
5076
5104
|
const paths = RulesyncPermissions.getSettablePaths();
|
|
5077
|
-
const filePath = join17(
|
|
5105
|
+
const filePath = join17(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
5078
5106
|
await removeFile(filePath);
|
|
5079
5107
|
const relativePathFromCwd = join17(paths.relativeDirPath, paths.relativeFilePath);
|
|
5080
5108
|
return {
|
|
@@ -5212,7 +5240,7 @@ async function putRule({
|
|
|
5212
5240
|
);
|
|
5213
5241
|
}
|
|
5214
5242
|
const rule = new RulesyncRule({
|
|
5215
|
-
|
|
5243
|
+
outputRoot: process.cwd(),
|
|
5216
5244
|
relativeDirPath: RULESYNC_RULES_RELATIVE_DIR_PATH,
|
|
5217
5245
|
relativeFilePath: filename,
|
|
5218
5246
|
frontmatter,
|
|
@@ -5419,7 +5447,7 @@ async function putSkill({
|
|
|
5419
5447
|
}
|
|
5420
5448
|
const aiDirFiles = otherFiles.map(mcpSkillFileToAiDirFile);
|
|
5421
5449
|
const skill = new RulesyncSkill({
|
|
5422
|
-
|
|
5450
|
+
outputRoot: process.cwd(),
|
|
5423
5451
|
relativeDirPath: RULESYNC_SKILLS_RELATIVE_DIR_PATH,
|
|
5424
5452
|
dirName,
|
|
5425
5453
|
frontmatter,
|
|
@@ -5636,7 +5664,7 @@ async function putSubagent({
|
|
|
5636
5664
|
);
|
|
5637
5665
|
}
|
|
5638
5666
|
const subagent = new RulesyncSubagent({
|
|
5639
|
-
|
|
5667
|
+
outputRoot: process.cwd(),
|
|
5640
5668
|
relativeDirPath: RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH,
|
|
5641
5669
|
relativeFilePath: filename,
|
|
5642
5670
|
frontmatter,
|
|
@@ -6435,7 +6463,7 @@ function wrapCommand({
|
|
|
6435
6463
|
}
|
|
6436
6464
|
|
|
6437
6465
|
// src/cli/index.ts
|
|
6438
|
-
var getVersion = () => "8.
|
|
6466
|
+
var getVersion = () => "8.13.0";
|
|
6439
6467
|
function wrapCommand2(name, errorCode, handler) {
|
|
6440
6468
|
return wrapCommand({ name, errorCode, handler, getVersion });
|
|
6441
6469
|
}
|
|
@@ -6552,8 +6580,12 @@ var main = async () => {
|
|
|
6552
6580
|
`Comma-separated list of features to generate (${ALL_FEATURES.join(",")}) or '*' for all`,
|
|
6553
6581
|
parseCommaSeparatedList
|
|
6554
6582
|
).option("--delete", "Delete all existing files in output directories before generating").option(
|
|
6583
|
+
"-o, --output-roots <paths>",
|
|
6584
|
+
"Output root directories to generate files into (comma-separated for multiple paths)",
|
|
6585
|
+
parseCommaSeparatedList
|
|
6586
|
+
).option(
|
|
6555
6587
|
"-b, --base-dir <paths>",
|
|
6556
|
-
"
|
|
6588
|
+
"[Deprecated] Use --output-roots instead. Output root directories (comma-separated for multiple paths)",
|
|
6557
6589
|
parseCommaSeparatedList
|
|
6558
6590
|
).option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").option("-c, --config <path>", "Path to configuration file").option("-g, --global", "Generate for global(user scope) configuration files").option(
|
|
6559
6591
|
"--simulate-commands",
|
|
@@ -6564,6 +6596,9 @@ var main = async () => {
|
|
|
6564
6596
|
).option(
|
|
6565
6597
|
"--simulate-skills",
|
|
6566
6598
|
"Generate simulated skills. This feature is only available for copilot, cursor and codexcli."
|
|
6599
|
+
).option(
|
|
6600
|
+
"--input-root <path>",
|
|
6601
|
+
"Path to the directory containing .rulesync/ (parent of .rulesync/)"
|
|
6567
6602
|
).option("--dry-run", "Dry run: show changes without writing files").option("--check", "Check if files are up to date (exits with code 1 if changes needed)").action(
|
|
6568
6603
|
wrapCommand2("generate", "GENERATION_FAILED", async (logger5, options) => {
|
|
6569
6604
|
await generateCommand(logger5, options);
|