rulesync 5.8.0 → 5.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/README.md +1 -0
- package/dist/index.cjs +307 -171
- package/dist/index.js +296 -160
- package/package.json +11 -11
package/dist/index.js
CHANGED
|
@@ -93,9 +93,6 @@ var Logger = class {
|
|
|
93
93
|
};
|
|
94
94
|
var logger = new Logger();
|
|
95
95
|
|
|
96
|
-
// src/cli/commands/generate.ts
|
|
97
|
-
import { intersection } from "es-toolkit";
|
|
98
|
-
|
|
99
96
|
// src/config/config-resolver.ts
|
|
100
97
|
import { parse as parseJsonc } from "jsonc-parser";
|
|
101
98
|
import { resolve as resolve2 } from "path";
|
|
@@ -467,6 +464,10 @@ function getBaseDirsInLightOfGlobal({
|
|
|
467
464
|
return resolvedBaseDirs;
|
|
468
465
|
}
|
|
469
466
|
|
|
467
|
+
// src/lib/generate.ts
|
|
468
|
+
import { intersection } from "es-toolkit";
|
|
469
|
+
import { join as join96 } from "path";
|
|
470
|
+
|
|
470
471
|
// src/constants/rulesync-paths.ts
|
|
471
472
|
import { join as join2 } from "path";
|
|
472
473
|
var RULESYNC_CONFIG_RELATIVE_FILE_PATH = "rulesync.jsonc";
|
|
@@ -8916,7 +8917,8 @@ import { join as join74 } from "path";
|
|
|
8916
8917
|
import { basename as basename22, join as join73 } from "path";
|
|
8917
8918
|
import { z as z38 } from "zod/mini";
|
|
8918
8919
|
var RulesyncRuleFrontmatterSchema = z38.object({
|
|
8919
|
-
root: z38.optional(z38.
|
|
8920
|
+
root: z38.optional(z38.boolean()),
|
|
8921
|
+
localRoot: z38.optional(z38.boolean()),
|
|
8920
8922
|
targets: z38.optional(RulesyncTargetsSchema),
|
|
8921
8923
|
description: z38.optional(z38.string()),
|
|
8922
8924
|
globs: z38.optional(z38.array(z38.string())),
|
|
@@ -9024,6 +9026,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
|
|
|
9024
9026
|
}
|
|
9025
9027
|
const validatedFrontmatter = {
|
|
9026
9028
|
root: result.data.root ?? false,
|
|
9029
|
+
localRoot: result.data.localRoot ?? false,
|
|
9027
9030
|
targets: result.data.targets ?? ["*"],
|
|
9028
9031
|
description: result.data.description ?? "",
|
|
9029
9032
|
globs: result.data.globs ?? [],
|
|
@@ -9057,6 +9060,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
|
|
|
9057
9060
|
}
|
|
9058
9061
|
const validatedFrontmatter = {
|
|
9059
9062
|
root: result.data.root ?? false,
|
|
9063
|
+
localRoot: result.data.localRoot ?? false,
|
|
9060
9064
|
targets: result.data.targets ?? ["*"],
|
|
9061
9065
|
description: result.data.description ?? "",
|
|
9062
9066
|
globs: result.data.globs ?? [],
|
|
@@ -11699,9 +11703,11 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
11699
11703
|
const rulesyncRules = rulesyncFiles.filter(
|
|
11700
11704
|
(file) => file instanceof RulesyncRule
|
|
11701
11705
|
);
|
|
11706
|
+
const localRootRules = rulesyncRules.filter((rule) => rule.getFrontmatter().localRoot);
|
|
11707
|
+
const nonLocalRootRules = rulesyncRules.filter((rule) => !rule.getFrontmatter().localRoot);
|
|
11702
11708
|
const factory = this.getFactory(this.toolTarget);
|
|
11703
11709
|
const { meta } = factory;
|
|
11704
|
-
const toolRules =
|
|
11710
|
+
const toolRules = nonLocalRootRules.map((rulesyncRule) => {
|
|
11705
11711
|
if (!factory.class.isTargetedByRulesyncRule(rulesyncRule)) {
|
|
11706
11712
|
return null;
|
|
11707
11713
|
}
|
|
@@ -11712,6 +11718,12 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
11712
11718
|
global: this.global
|
|
11713
11719
|
});
|
|
11714
11720
|
}).filter((rule) => rule !== null);
|
|
11721
|
+
if (localRootRules.length > 0 && !this.global) {
|
|
11722
|
+
const localRootRule = localRootRules[0];
|
|
11723
|
+
if (localRootRule && factory.class.isTargetedByRulesyncRule(localRootRule)) {
|
|
11724
|
+
this.handleLocalRootRule(toolRules, localRootRule, factory);
|
|
11725
|
+
}
|
|
11726
|
+
}
|
|
11715
11727
|
const isSimulated = this.simulateCommands || this.simulateSubagents || this.simulateSkills;
|
|
11716
11728
|
if (isSimulated && meta.createsSeparateConventionsRule && meta.additionalConventions) {
|
|
11717
11729
|
const conventionsContent = this.generateAdditionalConventionsSectionFromMeta(meta);
|
|
@@ -11766,6 +11778,50 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
11766
11778
|
};
|
|
11767
11779
|
});
|
|
11768
11780
|
}
|
|
11781
|
+
/**
|
|
11782
|
+
* Handle localRoot rule generation based on tool target.
|
|
11783
|
+
* - Claude Code: generates `.claude/CLAUDE.local.md`
|
|
11784
|
+
* - Claude Code Legacy: generates `./CLAUDE.local.md`
|
|
11785
|
+
* - Other tools: appends content to the root file with one blank line separator
|
|
11786
|
+
*/
|
|
11787
|
+
handleLocalRootRule(toolRules, localRootRule, _factory) {
|
|
11788
|
+
const localRootBody = localRootRule.getBody();
|
|
11789
|
+
if (this.toolTarget === "claudecode") {
|
|
11790
|
+
const paths = ClaudecodeRule.getSettablePaths({ global: this.global });
|
|
11791
|
+
toolRules.push(
|
|
11792
|
+
new ClaudecodeRule({
|
|
11793
|
+
baseDir: this.baseDir,
|
|
11794
|
+
relativeDirPath: paths.root.relativeDirPath,
|
|
11795
|
+
relativeFilePath: "CLAUDE.local.md",
|
|
11796
|
+
frontmatter: {},
|
|
11797
|
+
body: localRootBody,
|
|
11798
|
+
validate: true,
|
|
11799
|
+
root: true
|
|
11800
|
+
// Treat as root so it doesn't have frontmatter
|
|
11801
|
+
})
|
|
11802
|
+
);
|
|
11803
|
+
} else if (this.toolTarget === "claudecode-legacy") {
|
|
11804
|
+
const paths = ClaudecodeLegacyRule.getSettablePaths({ global: this.global });
|
|
11805
|
+
toolRules.push(
|
|
11806
|
+
new ClaudecodeLegacyRule({
|
|
11807
|
+
baseDir: this.baseDir,
|
|
11808
|
+
relativeDirPath: paths.root.relativeDirPath,
|
|
11809
|
+
relativeFilePath: "CLAUDE.local.md",
|
|
11810
|
+
fileContent: localRootBody,
|
|
11811
|
+
validate: true,
|
|
11812
|
+
root: true
|
|
11813
|
+
// Treat as root so it doesn't have frontmatter
|
|
11814
|
+
})
|
|
11815
|
+
);
|
|
11816
|
+
} else {
|
|
11817
|
+
const rootRule = toolRules.find((rule) => rule.isRoot());
|
|
11818
|
+
if (rootRule) {
|
|
11819
|
+
const currentContent = rootRule.getFileContent();
|
|
11820
|
+
const newContent = currentContent + "\n\n" + localRootBody;
|
|
11821
|
+
rootRule.setFileContent(newContent);
|
|
11822
|
+
}
|
|
11823
|
+
}
|
|
11824
|
+
}
|
|
11769
11825
|
/**
|
|
11770
11826
|
* Generate reference section based on meta configuration.
|
|
11771
11827
|
*/
|
|
@@ -11834,6 +11890,18 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
11834
11890
|
if (rootRules.length > 1) {
|
|
11835
11891
|
throw new Error("Multiple root rulesync rules found");
|
|
11836
11892
|
}
|
|
11893
|
+
if (rootRules.length === 0 && rulesyncRules.length > 0) {
|
|
11894
|
+
logger.warn(
|
|
11895
|
+
`No root rulesync rule file found. Consider adding 'root: true' to one of your rule files in ${RULESYNC_RULES_RELATIVE_DIR_PATH}.`
|
|
11896
|
+
);
|
|
11897
|
+
}
|
|
11898
|
+
const localRootRules = rulesyncRules.filter((rule) => rule.getFrontmatter().localRoot);
|
|
11899
|
+
if (localRootRules.length > 1) {
|
|
11900
|
+
throw new Error("Multiple localRoot rules found. Only one rule can have localRoot: true");
|
|
11901
|
+
}
|
|
11902
|
+
if (localRootRules.length > 0 && rootRules.length === 0) {
|
|
11903
|
+
throw new Error("localRoot: true requires a root: true rule to exist");
|
|
11904
|
+
}
|
|
11837
11905
|
if (this.global) {
|
|
11838
11906
|
const nonRootRules = rulesyncRules.filter((rule) => !rule.getFrontmatter().root);
|
|
11839
11907
|
if (nonRootRules.length > 0) {
|
|
@@ -11841,6 +11909,11 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
11841
11909
|
`${nonRootRules.length} non-root rulesync rules found, but it's in global mode, so ignoring them`
|
|
11842
11910
|
);
|
|
11843
11911
|
}
|
|
11912
|
+
if (localRootRules.length > 0) {
|
|
11913
|
+
logger.warn(
|
|
11914
|
+
`${localRootRules.length} localRoot rules found, but localRoot is not supported in global mode, ignoring them`
|
|
11915
|
+
);
|
|
11916
|
+
}
|
|
11844
11917
|
return rootRules;
|
|
11845
11918
|
}
|
|
11846
11919
|
return rulesyncRules;
|
|
@@ -11894,6 +11967,29 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
11894
11967
|
);
|
|
11895
11968
|
})();
|
|
11896
11969
|
logger.debug(`Found ${rootToolRules.length} root tool rule files`);
|
|
11970
|
+
const localRootToolRules = await (async () => {
|
|
11971
|
+
if (!forDeletion) {
|
|
11972
|
+
return [];
|
|
11973
|
+
}
|
|
11974
|
+
if (this.toolTarget !== "claudecode" && this.toolTarget !== "claudecode-legacy") {
|
|
11975
|
+
return [];
|
|
11976
|
+
}
|
|
11977
|
+
if (!settablePaths.root) {
|
|
11978
|
+
return [];
|
|
11979
|
+
}
|
|
11980
|
+
const localRootFilePaths = await findFilesByGlobs(
|
|
11981
|
+
join95(this.baseDir, settablePaths.root.relativeDirPath ?? ".", "CLAUDE.local.md")
|
|
11982
|
+
);
|
|
11983
|
+
return localRootFilePaths.map(
|
|
11984
|
+
(filePath) => factory.class.forDeletion({
|
|
11985
|
+
baseDir: this.baseDir,
|
|
11986
|
+
relativeDirPath: settablePaths.root?.relativeDirPath ?? ".",
|
|
11987
|
+
relativeFilePath: basename24(filePath),
|
|
11988
|
+
global: this.global
|
|
11989
|
+
})
|
|
11990
|
+
).filter((rule) => rule.isDeletable());
|
|
11991
|
+
})();
|
|
11992
|
+
logger.debug(`Found ${localRootToolRules.length} local root tool rule files for deletion`);
|
|
11897
11993
|
const nonRootToolRules = await (async () => {
|
|
11898
11994
|
if (!settablePaths.nonRoot) {
|
|
11899
11995
|
return [];
|
|
@@ -11922,7 +12018,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
11922
12018
|
);
|
|
11923
12019
|
})();
|
|
11924
12020
|
logger.debug(`Found ${nonRootToolRules.length} non-root tool rule files`);
|
|
11925
|
-
return [...rootToolRules, ...nonRootToolRules];
|
|
12021
|
+
return [...rootToolRules, ...localRootToolRules, ...nonRootToolRules];
|
|
11926
12022
|
} catch (error) {
|
|
11927
12023
|
logger.error(`Failed to load tool files: ${formatError(error)}`);
|
|
11928
12024
|
return [];
|
|
@@ -12042,51 +12138,34 @@ ${toonContent}`;
|
|
|
12042
12138
|
}
|
|
12043
12139
|
};
|
|
12044
12140
|
|
|
12045
|
-
// src/
|
|
12046
|
-
async function
|
|
12047
|
-
|
|
12048
|
-
|
|
12049
|
-
|
|
12050
|
-
|
|
12051
|
-
});
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
|
|
12055
|
-
|
|
12056
|
-
}
|
|
12057
|
-
|
|
12058
|
-
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
|
|
12062
|
-
|
|
12063
|
-
|
|
12141
|
+
// src/lib/generate.ts
|
|
12142
|
+
async function checkRulesyncDirExists(params) {
|
|
12143
|
+
return fileExists(join96(params.baseDir, RULESYNC_RELATIVE_DIR_PATH));
|
|
12144
|
+
}
|
|
12145
|
+
async function generate(params) {
|
|
12146
|
+
const { config } = params;
|
|
12147
|
+
const ignoreCount = await generateIgnoreCore({ config });
|
|
12148
|
+
const mcpCount = await generateMcpCore({ config });
|
|
12149
|
+
const commandsCount = await generateCommandsCore({ config });
|
|
12150
|
+
const subagentsCount = await generateSubagentsCore({ config });
|
|
12151
|
+
const skillsResult = await generateSkillsCore({ config });
|
|
12152
|
+
const rulesCount = await generateRulesCore({ config, skills: skillsResult.skills });
|
|
12153
|
+
return {
|
|
12154
|
+
rulesCount,
|
|
12155
|
+
ignoreCount,
|
|
12156
|
+
mcpCount,
|
|
12157
|
+
commandsCount,
|
|
12158
|
+
subagentsCount,
|
|
12159
|
+
skillsCount: skillsResult.count,
|
|
12064
12160
|
skills: skillsResult.skills
|
|
12065
|
-
}
|
|
12066
|
-
const totalGenerated = totalRulesOutputs + totalMcpOutputs + totalCommandOutputs + totalIgnoreOutputs + totalSubagentOutputs + skillsResult.totalOutputs;
|
|
12067
|
-
if (totalGenerated === 0) {
|
|
12068
|
-
const enabledFeatures = config.getFeatures().join(", ");
|
|
12069
|
-
logger.warn(`\u26A0\uFE0F No files generated for enabled features: ${enabledFeatures}`);
|
|
12070
|
-
return;
|
|
12071
|
-
}
|
|
12072
|
-
if (totalGenerated > 0) {
|
|
12073
|
-
const parts = [];
|
|
12074
|
-
if (totalRulesOutputs > 0) parts.push(`${totalRulesOutputs} rules`);
|
|
12075
|
-
if (totalIgnoreOutputs > 0) parts.push(`${totalIgnoreOutputs} ignore files`);
|
|
12076
|
-
if (totalMcpOutputs > 0) parts.push(`${totalMcpOutputs} MCP files`);
|
|
12077
|
-
if (totalCommandOutputs > 0) parts.push(`${totalCommandOutputs} commands`);
|
|
12078
|
-
if (totalSubagentOutputs > 0) parts.push(`${totalSubagentOutputs} subagents`);
|
|
12079
|
-
if (skillsResult.totalOutputs > 0) parts.push(`${skillsResult.totalOutputs} skills`);
|
|
12080
|
-
logger.success(`\u{1F389} All done! Generated ${totalGenerated} file(s) total (${parts.join(" + ")})`);
|
|
12081
|
-
}
|
|
12161
|
+
};
|
|
12082
12162
|
}
|
|
12083
|
-
async function
|
|
12163
|
+
async function generateRulesCore(params) {
|
|
12164
|
+
const { config, skills } = params;
|
|
12084
12165
|
if (!config.getFeatures().includes("rules")) {
|
|
12085
|
-
logger.debug("Skipping rule generation (not in --features)");
|
|
12086
12166
|
return 0;
|
|
12087
12167
|
}
|
|
12088
|
-
let
|
|
12089
|
-
logger.info("Generating rule files...");
|
|
12168
|
+
let totalCount = 0;
|
|
12090
12169
|
const toolTargets = intersection(
|
|
12091
12170
|
config.getTargets(),
|
|
12092
12171
|
RulesProcessor.getToolTargets({ global: config.getGlobal() })
|
|
@@ -12100,7 +12179,7 @@ async function generateRules(config, options) {
|
|
|
12100
12179
|
simulateCommands: config.getSimulateCommands(),
|
|
12101
12180
|
simulateSubagents: config.getSimulateSubagents(),
|
|
12102
12181
|
simulateSkills: config.getSimulateSkills(),
|
|
12103
|
-
skills
|
|
12182
|
+
skills
|
|
12104
12183
|
});
|
|
12105
12184
|
if (config.getDelete()) {
|
|
12106
12185
|
const oldToolFiles = await processor.loadToolFiles({ forDeletion: true });
|
|
@@ -12109,23 +12188,20 @@ async function generateRules(config, options) {
|
|
|
12109
12188
|
const rulesyncFiles = await processor.loadRulesyncFiles();
|
|
12110
12189
|
const toolFiles = await processor.convertRulesyncFilesToToolFiles(rulesyncFiles);
|
|
12111
12190
|
const writtenCount = await processor.writeAiFiles(toolFiles);
|
|
12112
|
-
|
|
12113
|
-
logger.success(`Generated ${writtenCount} ${toolTarget} rule(s) in ${baseDir}`);
|
|
12191
|
+
totalCount += writtenCount;
|
|
12114
12192
|
}
|
|
12115
12193
|
}
|
|
12116
|
-
return
|
|
12194
|
+
return totalCount;
|
|
12117
12195
|
}
|
|
12118
|
-
async function
|
|
12196
|
+
async function generateIgnoreCore(params) {
|
|
12197
|
+
const { config } = params;
|
|
12119
12198
|
if (!config.getFeatures().includes("ignore")) {
|
|
12120
|
-
logger.debug("Skipping ignore file generation (not in --features)");
|
|
12121
12199
|
return 0;
|
|
12122
12200
|
}
|
|
12123
12201
|
if (config.getGlobal()) {
|
|
12124
|
-
logger.debug("Skipping ignore file generation (not supported in global mode)");
|
|
12125
12202
|
return 0;
|
|
12126
12203
|
}
|
|
12127
|
-
let
|
|
12128
|
-
logger.info("Generating ignore files...");
|
|
12204
|
+
let totalCount = 0;
|
|
12129
12205
|
for (const toolTarget of intersection(config.getTargets(), IgnoreProcessor.getToolTargets())) {
|
|
12130
12206
|
for (const baseDir of config.getBaseDirs()) {
|
|
12131
12207
|
try {
|
|
@@ -12141,30 +12217,24 @@ async function generateIgnore(config) {
|
|
|
12141
12217
|
if (rulesyncFiles.length > 0) {
|
|
12142
12218
|
const toolFiles = await processor.convertRulesyncFilesToToolFiles(rulesyncFiles);
|
|
12143
12219
|
const writtenCount = await processor.writeAiFiles(toolFiles);
|
|
12144
|
-
|
|
12145
|
-
logger.success(`Generated ${writtenCount} ${toolTarget} ignore file(s) in ${baseDir}`);
|
|
12220
|
+
totalCount += writtenCount;
|
|
12146
12221
|
}
|
|
12147
12222
|
} catch (error) {
|
|
12148
12223
|
logger.warn(
|
|
12149
|
-
`Failed to generate ${toolTarget} ignore files for ${baseDir}
|
|
12150
|
-
error instanceof Error ? error.message : String(error)
|
|
12224
|
+
`Failed to generate ${toolTarget} ignore files for ${baseDir}: ${formatError(error)}`
|
|
12151
12225
|
);
|
|
12152
12226
|
continue;
|
|
12153
12227
|
}
|
|
12154
12228
|
}
|
|
12155
12229
|
}
|
|
12156
|
-
return
|
|
12230
|
+
return totalCount;
|
|
12157
12231
|
}
|
|
12158
|
-
async function
|
|
12232
|
+
async function generateMcpCore(params) {
|
|
12233
|
+
const { config } = params;
|
|
12159
12234
|
if (!config.getFeatures().includes("mcp")) {
|
|
12160
|
-
logger.debug("Skipping MCP configuration generation (not in --features)");
|
|
12161
12235
|
return 0;
|
|
12162
12236
|
}
|
|
12163
|
-
let
|
|
12164
|
-
logger.info("Generating MCP files...");
|
|
12165
|
-
if (config.getModularMcp()) {
|
|
12166
|
-
logger.info("\u2139\uFE0F Modular MCP support is experimental.");
|
|
12167
|
-
}
|
|
12237
|
+
let totalCount = 0;
|
|
12168
12238
|
const toolTargets = intersection(
|
|
12169
12239
|
config.getTargets(),
|
|
12170
12240
|
McpProcessor.getToolTargets({ global: config.getGlobal() })
|
|
@@ -12184,19 +12254,17 @@ async function generateMcp(config) {
|
|
|
12184
12254
|
const rulesyncFiles = await processor.loadRulesyncFiles();
|
|
12185
12255
|
const toolFiles = await processor.convertRulesyncFilesToToolFiles(rulesyncFiles);
|
|
12186
12256
|
const writtenCount = await processor.writeAiFiles(toolFiles);
|
|
12187
|
-
|
|
12188
|
-
logger.success(`Generated ${writtenCount} ${toolTarget} MCP configuration(s) in ${baseDir}`);
|
|
12257
|
+
totalCount += writtenCount;
|
|
12189
12258
|
}
|
|
12190
12259
|
}
|
|
12191
|
-
return
|
|
12260
|
+
return totalCount;
|
|
12192
12261
|
}
|
|
12193
|
-
async function
|
|
12262
|
+
async function generateCommandsCore(params) {
|
|
12263
|
+
const { config } = params;
|
|
12194
12264
|
if (!config.getFeatures().includes("commands")) {
|
|
12195
|
-
logger.debug("Skipping command file generation (not in --features)");
|
|
12196
12265
|
return 0;
|
|
12197
12266
|
}
|
|
12198
|
-
let
|
|
12199
|
-
logger.info("Generating command files...");
|
|
12267
|
+
let totalCount = 0;
|
|
12200
12268
|
const toolTargets = intersection(
|
|
12201
12269
|
config.getTargets(),
|
|
12202
12270
|
CommandsProcessor.getToolTargets({
|
|
@@ -12218,19 +12286,17 @@ async function generateCommands(config) {
|
|
|
12218
12286
|
const rulesyncFiles = await processor.loadRulesyncFiles();
|
|
12219
12287
|
const toolFiles = await processor.convertRulesyncFilesToToolFiles(rulesyncFiles);
|
|
12220
12288
|
const writtenCount = await processor.writeAiFiles(toolFiles);
|
|
12221
|
-
|
|
12222
|
-
logger.success(`Generated ${writtenCount} ${toolTarget} command(s) in ${baseDir}`);
|
|
12289
|
+
totalCount += writtenCount;
|
|
12223
12290
|
}
|
|
12224
12291
|
}
|
|
12225
|
-
return
|
|
12292
|
+
return totalCount;
|
|
12226
12293
|
}
|
|
12227
|
-
async function
|
|
12294
|
+
async function generateSubagentsCore(params) {
|
|
12295
|
+
const { config } = params;
|
|
12228
12296
|
if (!config.getFeatures().includes("subagents")) {
|
|
12229
|
-
logger.debug("Skipping subagent file generation (not in --features)");
|
|
12230
12297
|
return 0;
|
|
12231
12298
|
}
|
|
12232
|
-
let
|
|
12233
|
-
logger.info("Generating subagent files...");
|
|
12299
|
+
let totalCount = 0;
|
|
12234
12300
|
const toolTargets = intersection(
|
|
12235
12301
|
config.getTargets(),
|
|
12236
12302
|
SubagentsProcessor.getToolTargets({
|
|
@@ -12252,20 +12318,18 @@ async function generateSubagents(config) {
|
|
|
12252
12318
|
const rulesyncFiles = await processor.loadRulesyncFiles();
|
|
12253
12319
|
const toolFiles = await processor.convertRulesyncFilesToToolFiles(rulesyncFiles);
|
|
12254
12320
|
const writtenCount = await processor.writeAiFiles(toolFiles);
|
|
12255
|
-
|
|
12256
|
-
logger.success(`Generated ${writtenCount} ${toolTarget} subagent(s) in ${baseDir}`);
|
|
12321
|
+
totalCount += writtenCount;
|
|
12257
12322
|
}
|
|
12258
12323
|
}
|
|
12259
|
-
return
|
|
12324
|
+
return totalCount;
|
|
12260
12325
|
}
|
|
12261
|
-
async function
|
|
12326
|
+
async function generateSkillsCore(params) {
|
|
12327
|
+
const { config } = params;
|
|
12262
12328
|
if (!config.getFeatures().includes("skills")) {
|
|
12263
|
-
|
|
12264
|
-
return { totalOutputs: 0, skills: [] };
|
|
12329
|
+
return { count: 0, skills: [] };
|
|
12265
12330
|
}
|
|
12266
|
-
let
|
|
12331
|
+
let totalCount = 0;
|
|
12267
12332
|
const allSkills = [];
|
|
12268
|
-
logger.info("Generating skill files...");
|
|
12269
12333
|
const toolTargets = intersection(
|
|
12270
12334
|
config.getTargets(),
|
|
12271
12335
|
SkillsProcessor.getToolTargets({
|
|
@@ -12292,15 +12356,84 @@ async function generateSkills(config) {
|
|
|
12292
12356
|
}
|
|
12293
12357
|
const toolDirs = await processor.convertRulesyncDirsToToolDirs(rulesyncDirs);
|
|
12294
12358
|
const writtenCount = await processor.writeAiDirs(toolDirs);
|
|
12295
|
-
|
|
12296
|
-
|
|
12359
|
+
totalCount += writtenCount;
|
|
12360
|
+
}
|
|
12361
|
+
}
|
|
12362
|
+
return { count: totalCount, skills: allSkills };
|
|
12363
|
+
}
|
|
12364
|
+
|
|
12365
|
+
// src/cli/commands/generate.ts
|
|
12366
|
+
async function generateCommand(options) {
|
|
12367
|
+
const config = await ConfigResolver.resolve(options);
|
|
12368
|
+
logger.configure({
|
|
12369
|
+
verbose: config.getVerbose(),
|
|
12370
|
+
silent: config.getSilent()
|
|
12371
|
+
});
|
|
12372
|
+
logger.info("Generating files...");
|
|
12373
|
+
if (!await checkRulesyncDirExists({ baseDir: config.getBaseDirs()[0] ?? process.cwd() })) {
|
|
12374
|
+
logger.error("\u274C .rulesync directory not found. Run 'rulesync init' first.");
|
|
12375
|
+
process.exit(1);
|
|
12376
|
+
}
|
|
12377
|
+
logger.info(`Base directories: ${config.getBaseDirs().join(", ")}`);
|
|
12378
|
+
const features = config.getFeatures();
|
|
12379
|
+
if (features.includes("ignore")) {
|
|
12380
|
+
logger.info("Generating ignore files...");
|
|
12381
|
+
}
|
|
12382
|
+
if (features.includes("mcp")) {
|
|
12383
|
+
logger.info("Generating MCP files...");
|
|
12384
|
+
if (config.getModularMcp()) {
|
|
12385
|
+
logger.info("\u2139\uFE0F Modular MCP support is experimental.");
|
|
12297
12386
|
}
|
|
12298
12387
|
}
|
|
12299
|
-
|
|
12388
|
+
if (features.includes("commands")) {
|
|
12389
|
+
logger.info("Generating command files...");
|
|
12390
|
+
}
|
|
12391
|
+
if (features.includes("subagents")) {
|
|
12392
|
+
logger.info("Generating subagent files...");
|
|
12393
|
+
}
|
|
12394
|
+
if (features.includes("skills")) {
|
|
12395
|
+
logger.info("Generating skill files...");
|
|
12396
|
+
}
|
|
12397
|
+
if (features.includes("rules")) {
|
|
12398
|
+
logger.info("Generating rule files...");
|
|
12399
|
+
}
|
|
12400
|
+
const result = await generate({ config });
|
|
12401
|
+
if (result.ignoreCount > 0) {
|
|
12402
|
+
logger.success(`Generated ${result.ignoreCount} ignore file(s)`);
|
|
12403
|
+
}
|
|
12404
|
+
if (result.mcpCount > 0) {
|
|
12405
|
+
logger.success(`Generated ${result.mcpCount} MCP configuration(s)`);
|
|
12406
|
+
}
|
|
12407
|
+
if (result.commandsCount > 0) {
|
|
12408
|
+
logger.success(`Generated ${result.commandsCount} command(s)`);
|
|
12409
|
+
}
|
|
12410
|
+
if (result.subagentsCount > 0) {
|
|
12411
|
+
logger.success(`Generated ${result.subagentsCount} subagent(s)`);
|
|
12412
|
+
}
|
|
12413
|
+
if (result.skillsCount > 0) {
|
|
12414
|
+
logger.success(`Generated ${result.skillsCount} skill(s)`);
|
|
12415
|
+
}
|
|
12416
|
+
if (result.rulesCount > 0) {
|
|
12417
|
+
logger.success(`Generated ${result.rulesCount} rule(s)`);
|
|
12418
|
+
}
|
|
12419
|
+
const totalGenerated = result.rulesCount + result.ignoreCount + result.mcpCount + result.commandsCount + result.subagentsCount + result.skillsCount;
|
|
12420
|
+
if (totalGenerated === 0) {
|
|
12421
|
+
const enabledFeatures = features.join(", ");
|
|
12422
|
+
logger.warn(`\u26A0\uFE0F No files generated for enabled features: ${enabledFeatures}`);
|
|
12423
|
+
return;
|
|
12424
|
+
}
|
|
12425
|
+
const parts = [];
|
|
12426
|
+
if (result.rulesCount > 0) parts.push(`${result.rulesCount} rules`);
|
|
12427
|
+
if (result.ignoreCount > 0) parts.push(`${result.ignoreCount} ignore files`);
|
|
12428
|
+
if (result.mcpCount > 0) parts.push(`${result.mcpCount} MCP files`);
|
|
12429
|
+
if (result.commandsCount > 0) parts.push(`${result.commandsCount} commands`);
|
|
12430
|
+
if (result.subagentsCount > 0) parts.push(`${result.subagentsCount} subagents`);
|
|
12431
|
+
if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
|
|
12432
|
+
logger.success(`\u{1F389} All done! Generated ${totalGenerated} file(s) total (${parts.join(" + ")})`);
|
|
12300
12433
|
}
|
|
12301
12434
|
|
|
12302
12435
|
// src/cli/commands/gitignore.ts
|
|
12303
|
-
import { join as
|
|
12436
|
+
import { join as join97 } from "path";
|
|
12304
12437
|
var RULESYNC_HEADER = "# Generated by Rulesync";
|
|
12305
12438
|
var LEGACY_RULESYNC_HEADER = "# Generated by rulesync - AI tool configuration files";
|
|
12306
12439
|
var RULESYNC_IGNORE_ENTRIES = [
|
|
@@ -12317,7 +12450,9 @@ var RULESYNC_IGNORE_ENTRIES = [
|
|
|
12317
12450
|
"**/.augment-guidelines",
|
|
12318
12451
|
// Claude Code
|
|
12319
12452
|
"**/CLAUDE.md",
|
|
12453
|
+
"**/CLAUDE.local.md",
|
|
12320
12454
|
"**/.claude/CLAUDE.md",
|
|
12455
|
+
"**/.claude/CLAUDE.local.md",
|
|
12321
12456
|
"**/.claude/memories/",
|
|
12322
12457
|
"**/.claude/rules/",
|
|
12323
12458
|
"**/.claude/commands/",
|
|
@@ -12389,6 +12524,7 @@ var RULESYNC_IGNORE_ENTRIES = [
|
|
|
12389
12524
|
"**/WARP.md",
|
|
12390
12525
|
// Others
|
|
12391
12526
|
"**/modular-mcp.json",
|
|
12527
|
+
".rulesync/rules/*.local.md",
|
|
12392
12528
|
"!.rulesync/.aiignore"
|
|
12393
12529
|
];
|
|
12394
12530
|
var isRulesyncHeader = (line) => {
|
|
@@ -12441,7 +12577,7 @@ var removeExistingRulesyncEntries = (content) => {
|
|
|
12441
12577
|
return result;
|
|
12442
12578
|
};
|
|
12443
12579
|
var gitignoreCommand = async () => {
|
|
12444
|
-
const gitignorePath =
|
|
12580
|
+
const gitignorePath = join97(process.cwd(), ".gitignore");
|
|
12445
12581
|
let gitignoreContent = "";
|
|
12446
12582
|
if (await fileExists(gitignorePath)) {
|
|
12447
12583
|
gitignoreContent = await readFileContent(gitignorePath);
|
|
@@ -12643,7 +12779,7 @@ async function importSkills(config, tool) {
|
|
|
12643
12779
|
}
|
|
12644
12780
|
|
|
12645
12781
|
// src/cli/commands/init.ts
|
|
12646
|
-
import { join as
|
|
12782
|
+
import { join as join98 } from "path";
|
|
12647
12783
|
async function initCommand() {
|
|
12648
12784
|
logger.info("Initializing rulesync...");
|
|
12649
12785
|
await ensureDir(RULESYNC_RELATIVE_DIR_PATH);
|
|
@@ -12821,14 +12957,14 @@ Keep the summary concise and ready to reuse in future tasks.`
|
|
|
12821
12957
|
await ensureDir(subagentPaths.relativeDirPath);
|
|
12822
12958
|
await ensureDir(skillPaths.relativeDirPath);
|
|
12823
12959
|
await ensureDir(ignorePaths.recommended.relativeDirPath);
|
|
12824
|
-
const ruleFilepath =
|
|
12960
|
+
const ruleFilepath = join98(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
|
|
12825
12961
|
if (!await fileExists(ruleFilepath)) {
|
|
12826
12962
|
await writeFileContent(ruleFilepath, sampleRuleFile.content);
|
|
12827
12963
|
logger.success(`Created ${ruleFilepath}`);
|
|
12828
12964
|
} else {
|
|
12829
12965
|
logger.info(`Skipped ${ruleFilepath} (already exists)`);
|
|
12830
12966
|
}
|
|
12831
|
-
const mcpFilepath =
|
|
12967
|
+
const mcpFilepath = join98(
|
|
12832
12968
|
mcpPaths.recommended.relativeDirPath,
|
|
12833
12969
|
mcpPaths.recommended.relativeFilePath
|
|
12834
12970
|
);
|
|
@@ -12838,30 +12974,30 @@ Keep the summary concise and ready to reuse in future tasks.`
|
|
|
12838
12974
|
} else {
|
|
12839
12975
|
logger.info(`Skipped ${mcpFilepath} (already exists)`);
|
|
12840
12976
|
}
|
|
12841
|
-
const commandFilepath =
|
|
12977
|
+
const commandFilepath = join98(commandPaths.relativeDirPath, sampleCommandFile.filename);
|
|
12842
12978
|
if (!await fileExists(commandFilepath)) {
|
|
12843
12979
|
await writeFileContent(commandFilepath, sampleCommandFile.content);
|
|
12844
12980
|
logger.success(`Created ${commandFilepath}`);
|
|
12845
12981
|
} else {
|
|
12846
12982
|
logger.info(`Skipped ${commandFilepath} (already exists)`);
|
|
12847
12983
|
}
|
|
12848
|
-
const subagentFilepath =
|
|
12984
|
+
const subagentFilepath = join98(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
|
|
12849
12985
|
if (!await fileExists(subagentFilepath)) {
|
|
12850
12986
|
await writeFileContent(subagentFilepath, sampleSubagentFile.content);
|
|
12851
12987
|
logger.success(`Created ${subagentFilepath}`);
|
|
12852
12988
|
} else {
|
|
12853
12989
|
logger.info(`Skipped ${subagentFilepath} (already exists)`);
|
|
12854
12990
|
}
|
|
12855
|
-
const skillDirPath =
|
|
12991
|
+
const skillDirPath = join98(skillPaths.relativeDirPath, sampleSkillFile.dirName);
|
|
12856
12992
|
await ensureDir(skillDirPath);
|
|
12857
|
-
const skillFilepath =
|
|
12993
|
+
const skillFilepath = join98(skillDirPath, SKILL_FILE_NAME);
|
|
12858
12994
|
if (!await fileExists(skillFilepath)) {
|
|
12859
12995
|
await writeFileContent(skillFilepath, sampleSkillFile.content);
|
|
12860
12996
|
logger.success(`Created ${skillFilepath}`);
|
|
12861
12997
|
} else {
|
|
12862
12998
|
logger.info(`Skipped ${skillFilepath} (already exists)`);
|
|
12863
12999
|
}
|
|
12864
|
-
const ignoreFilepath =
|
|
13000
|
+
const ignoreFilepath = join98(
|
|
12865
13001
|
ignorePaths.recommended.relativeDirPath,
|
|
12866
13002
|
ignorePaths.recommended.relativeFilePath
|
|
12867
13003
|
);
|
|
@@ -12880,12 +13016,12 @@ import { FastMCP } from "fastmcp";
|
|
|
12880
13016
|
import { z as z51 } from "zod/mini";
|
|
12881
13017
|
|
|
12882
13018
|
// src/mcp/commands.ts
|
|
12883
|
-
import { basename as basename25, join as
|
|
13019
|
+
import { basename as basename25, join as join99 } from "path";
|
|
12884
13020
|
import { z as z45 } from "zod/mini";
|
|
12885
13021
|
var maxCommandSizeBytes = 1024 * 1024;
|
|
12886
13022
|
var maxCommandsCount = 1e3;
|
|
12887
13023
|
async function listCommands() {
|
|
12888
|
-
const commandsDir =
|
|
13024
|
+
const commandsDir = join99(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
|
|
12889
13025
|
try {
|
|
12890
13026
|
const files = await listDirectoryFiles(commandsDir);
|
|
12891
13027
|
const mdFiles = files.filter((file) => file.endsWith(".md"));
|
|
@@ -12897,7 +13033,7 @@ async function listCommands() {
|
|
|
12897
13033
|
});
|
|
12898
13034
|
const frontmatter = command.getFrontmatter();
|
|
12899
13035
|
return {
|
|
12900
|
-
relativePathFromCwd:
|
|
13036
|
+
relativePathFromCwd: join99(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, file),
|
|
12901
13037
|
frontmatter
|
|
12902
13038
|
};
|
|
12903
13039
|
} catch (error) {
|
|
@@ -12923,7 +13059,7 @@ async function getCommand({ relativePathFromCwd }) {
|
|
|
12923
13059
|
relativeFilePath: filename
|
|
12924
13060
|
});
|
|
12925
13061
|
return {
|
|
12926
|
-
relativePathFromCwd:
|
|
13062
|
+
relativePathFromCwd: join99(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
|
|
12927
13063
|
frontmatter: command.getFrontmatter(),
|
|
12928
13064
|
body: command.getBody()
|
|
12929
13065
|
};
|
|
@@ -12952,7 +13088,7 @@ async function putCommand({
|
|
|
12952
13088
|
try {
|
|
12953
13089
|
const existingCommands = await listCommands();
|
|
12954
13090
|
const isUpdate = existingCommands.some(
|
|
12955
|
-
(command2) => command2.relativePathFromCwd ===
|
|
13091
|
+
(command2) => command2.relativePathFromCwd === join99(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
|
|
12956
13092
|
);
|
|
12957
13093
|
if (!isUpdate && existingCommands.length >= maxCommandsCount) {
|
|
12958
13094
|
throw new Error(`Maximum number of commands (${maxCommandsCount}) reached`);
|
|
@@ -12967,11 +13103,11 @@ async function putCommand({
|
|
|
12967
13103
|
fileContent,
|
|
12968
13104
|
validate: true
|
|
12969
13105
|
});
|
|
12970
|
-
const commandsDir =
|
|
13106
|
+
const commandsDir = join99(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
|
|
12971
13107
|
await ensureDir(commandsDir);
|
|
12972
13108
|
await writeFileContent(command.getFilePath(), command.getFileContent());
|
|
12973
13109
|
return {
|
|
12974
|
-
relativePathFromCwd:
|
|
13110
|
+
relativePathFromCwd: join99(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
|
|
12975
13111
|
frontmatter: command.getFrontmatter(),
|
|
12976
13112
|
body: command.getBody()
|
|
12977
13113
|
};
|
|
@@ -12987,11 +13123,11 @@ async function deleteCommand({ relativePathFromCwd }) {
|
|
|
12987
13123
|
intendedRootDir: process.cwd()
|
|
12988
13124
|
});
|
|
12989
13125
|
const filename = basename25(relativePathFromCwd);
|
|
12990
|
-
const fullPath =
|
|
13126
|
+
const fullPath = join99(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename);
|
|
12991
13127
|
try {
|
|
12992
13128
|
await removeFile(fullPath);
|
|
12993
13129
|
return {
|
|
12994
|
-
relativePathFromCwd:
|
|
13130
|
+
relativePathFromCwd: join99(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
|
|
12995
13131
|
};
|
|
12996
13132
|
} catch (error) {
|
|
12997
13133
|
throw new Error(`Failed to delete command file ${relativePathFromCwd}: ${formatError(error)}`, {
|
|
@@ -13016,7 +13152,7 @@ var commandToolSchemas = {
|
|
|
13016
13152
|
var commandTools = {
|
|
13017
13153
|
listCommands: {
|
|
13018
13154
|
name: "listCommands",
|
|
13019
|
-
description: `List all commands from ${
|
|
13155
|
+
description: `List all commands from ${join99(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
|
|
13020
13156
|
parameters: commandToolSchemas.listCommands,
|
|
13021
13157
|
execute: async () => {
|
|
13022
13158
|
const commands = await listCommands();
|
|
@@ -13058,11 +13194,11 @@ var commandTools = {
|
|
|
13058
13194
|
};
|
|
13059
13195
|
|
|
13060
13196
|
// src/mcp/ignore.ts
|
|
13061
|
-
import { join as
|
|
13197
|
+
import { join as join100 } from "path";
|
|
13062
13198
|
import { z as z46 } from "zod/mini";
|
|
13063
13199
|
var maxIgnoreFileSizeBytes = 100 * 1024;
|
|
13064
13200
|
async function getIgnoreFile() {
|
|
13065
|
-
const ignoreFilePath =
|
|
13201
|
+
const ignoreFilePath = join100(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
|
|
13066
13202
|
try {
|
|
13067
13203
|
const content = await readFileContent(ignoreFilePath);
|
|
13068
13204
|
return {
|
|
@@ -13076,7 +13212,7 @@ async function getIgnoreFile() {
|
|
|
13076
13212
|
}
|
|
13077
13213
|
}
|
|
13078
13214
|
async function putIgnoreFile({ content }) {
|
|
13079
|
-
const ignoreFilePath =
|
|
13215
|
+
const ignoreFilePath = join100(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
|
|
13080
13216
|
const contentSizeBytes = Buffer.byteLength(content, "utf8");
|
|
13081
13217
|
if (contentSizeBytes > maxIgnoreFileSizeBytes) {
|
|
13082
13218
|
throw new Error(
|
|
@@ -13097,8 +13233,8 @@ async function putIgnoreFile({ content }) {
|
|
|
13097
13233
|
}
|
|
13098
13234
|
}
|
|
13099
13235
|
async function deleteIgnoreFile() {
|
|
13100
|
-
const aiignorePath =
|
|
13101
|
-
const legacyIgnorePath =
|
|
13236
|
+
const aiignorePath = join100(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
|
|
13237
|
+
const legacyIgnorePath = join100(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
|
|
13102
13238
|
try {
|
|
13103
13239
|
await Promise.all([removeFile(aiignorePath), removeFile(legacyIgnorePath)]);
|
|
13104
13240
|
return {
|
|
@@ -13153,7 +13289,7 @@ var ignoreTools = {
|
|
|
13153
13289
|
};
|
|
13154
13290
|
|
|
13155
13291
|
// src/mcp/mcp.ts
|
|
13156
|
-
import { join as
|
|
13292
|
+
import { join as join101 } from "path";
|
|
13157
13293
|
import { z as z47 } from "zod/mini";
|
|
13158
13294
|
var maxMcpSizeBytes = 1024 * 1024;
|
|
13159
13295
|
async function getMcpFile() {
|
|
@@ -13163,7 +13299,7 @@ async function getMcpFile() {
|
|
|
13163
13299
|
validate: true,
|
|
13164
13300
|
modularMcp: config.getModularMcp()
|
|
13165
13301
|
});
|
|
13166
|
-
const relativePathFromCwd =
|
|
13302
|
+
const relativePathFromCwd = join101(
|
|
13167
13303
|
rulesyncMcp.getRelativeDirPath(),
|
|
13168
13304
|
rulesyncMcp.getRelativeFilePath()
|
|
13169
13305
|
);
|
|
@@ -13196,7 +13332,7 @@ async function putMcpFile({ content }) {
|
|
|
13196
13332
|
const paths = RulesyncMcp.getSettablePaths();
|
|
13197
13333
|
const relativeDirPath = paths.recommended.relativeDirPath;
|
|
13198
13334
|
const relativeFilePath = paths.recommended.relativeFilePath;
|
|
13199
|
-
const fullPath =
|
|
13335
|
+
const fullPath = join101(baseDir, relativeDirPath, relativeFilePath);
|
|
13200
13336
|
const rulesyncMcp = new RulesyncMcp({
|
|
13201
13337
|
baseDir,
|
|
13202
13338
|
relativeDirPath,
|
|
@@ -13205,9 +13341,9 @@ async function putMcpFile({ content }) {
|
|
|
13205
13341
|
validate: true,
|
|
13206
13342
|
modularMcp: config.getModularMcp()
|
|
13207
13343
|
});
|
|
13208
|
-
await ensureDir(
|
|
13344
|
+
await ensureDir(join101(baseDir, relativeDirPath));
|
|
13209
13345
|
await writeFileContent(fullPath, content);
|
|
13210
|
-
const relativePathFromCwd =
|
|
13346
|
+
const relativePathFromCwd = join101(relativeDirPath, relativeFilePath);
|
|
13211
13347
|
return {
|
|
13212
13348
|
relativePathFromCwd,
|
|
13213
13349
|
content: rulesyncMcp.getFileContent()
|
|
@@ -13222,15 +13358,15 @@ async function deleteMcpFile() {
|
|
|
13222
13358
|
try {
|
|
13223
13359
|
const baseDir = process.cwd();
|
|
13224
13360
|
const paths = RulesyncMcp.getSettablePaths();
|
|
13225
|
-
const recommendedPath =
|
|
13361
|
+
const recommendedPath = join101(
|
|
13226
13362
|
baseDir,
|
|
13227
13363
|
paths.recommended.relativeDirPath,
|
|
13228
13364
|
paths.recommended.relativeFilePath
|
|
13229
13365
|
);
|
|
13230
|
-
const legacyPath =
|
|
13366
|
+
const legacyPath = join101(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
|
|
13231
13367
|
await removeFile(recommendedPath);
|
|
13232
13368
|
await removeFile(legacyPath);
|
|
13233
|
-
const relativePathFromCwd =
|
|
13369
|
+
const relativePathFromCwd = join101(
|
|
13234
13370
|
paths.recommended.relativeDirPath,
|
|
13235
13371
|
paths.recommended.relativeFilePath
|
|
13236
13372
|
);
|
|
@@ -13281,12 +13417,12 @@ var mcpTools = {
|
|
|
13281
13417
|
};
|
|
13282
13418
|
|
|
13283
13419
|
// src/mcp/rules.ts
|
|
13284
|
-
import { basename as basename26, join as
|
|
13420
|
+
import { basename as basename26, join as join102 } from "path";
|
|
13285
13421
|
import { z as z48 } from "zod/mini";
|
|
13286
13422
|
var maxRuleSizeBytes = 1024 * 1024;
|
|
13287
13423
|
var maxRulesCount = 1e3;
|
|
13288
13424
|
async function listRules() {
|
|
13289
|
-
const rulesDir =
|
|
13425
|
+
const rulesDir = join102(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
|
|
13290
13426
|
try {
|
|
13291
13427
|
const files = await listDirectoryFiles(rulesDir);
|
|
13292
13428
|
const mdFiles = files.filter((file) => file.endsWith(".md"));
|
|
@@ -13299,7 +13435,7 @@ async function listRules() {
|
|
|
13299
13435
|
});
|
|
13300
13436
|
const frontmatter = rule.getFrontmatter();
|
|
13301
13437
|
return {
|
|
13302
|
-
relativePathFromCwd:
|
|
13438
|
+
relativePathFromCwd: join102(RULESYNC_RULES_RELATIVE_DIR_PATH, file),
|
|
13303
13439
|
frontmatter
|
|
13304
13440
|
};
|
|
13305
13441
|
} catch (error) {
|
|
@@ -13326,7 +13462,7 @@ async function getRule({ relativePathFromCwd }) {
|
|
|
13326
13462
|
validate: true
|
|
13327
13463
|
});
|
|
13328
13464
|
return {
|
|
13329
|
-
relativePathFromCwd:
|
|
13465
|
+
relativePathFromCwd: join102(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
|
|
13330
13466
|
frontmatter: rule.getFrontmatter(),
|
|
13331
13467
|
body: rule.getBody()
|
|
13332
13468
|
};
|
|
@@ -13355,7 +13491,7 @@ async function putRule({
|
|
|
13355
13491
|
try {
|
|
13356
13492
|
const existingRules = await listRules();
|
|
13357
13493
|
const isUpdate = existingRules.some(
|
|
13358
|
-
(rule2) => rule2.relativePathFromCwd ===
|
|
13494
|
+
(rule2) => rule2.relativePathFromCwd === join102(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
|
|
13359
13495
|
);
|
|
13360
13496
|
if (!isUpdate && existingRules.length >= maxRulesCount) {
|
|
13361
13497
|
throw new Error(`Maximum number of rules (${maxRulesCount}) reached`);
|
|
@@ -13368,11 +13504,11 @@ async function putRule({
|
|
|
13368
13504
|
body,
|
|
13369
13505
|
validate: true
|
|
13370
13506
|
});
|
|
13371
|
-
const rulesDir =
|
|
13507
|
+
const rulesDir = join102(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
|
|
13372
13508
|
await ensureDir(rulesDir);
|
|
13373
13509
|
await writeFileContent(rule.getFilePath(), rule.getFileContent());
|
|
13374
13510
|
return {
|
|
13375
|
-
relativePathFromCwd:
|
|
13511
|
+
relativePathFromCwd: join102(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
|
|
13376
13512
|
frontmatter: rule.getFrontmatter(),
|
|
13377
13513
|
body: rule.getBody()
|
|
13378
13514
|
};
|
|
@@ -13388,11 +13524,11 @@ async function deleteRule({ relativePathFromCwd }) {
|
|
|
13388
13524
|
intendedRootDir: process.cwd()
|
|
13389
13525
|
});
|
|
13390
13526
|
const filename = basename26(relativePathFromCwd);
|
|
13391
|
-
const fullPath =
|
|
13527
|
+
const fullPath = join102(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH, filename);
|
|
13392
13528
|
try {
|
|
13393
13529
|
await removeFile(fullPath);
|
|
13394
13530
|
return {
|
|
13395
|
-
relativePathFromCwd:
|
|
13531
|
+
relativePathFromCwd: join102(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
|
|
13396
13532
|
};
|
|
13397
13533
|
} catch (error) {
|
|
13398
13534
|
throw new Error(`Failed to delete rule file ${relativePathFromCwd}: ${formatError(error)}`, {
|
|
@@ -13417,7 +13553,7 @@ var ruleToolSchemas = {
|
|
|
13417
13553
|
var ruleTools = {
|
|
13418
13554
|
listRules: {
|
|
13419
13555
|
name: "listRules",
|
|
13420
|
-
description: `List all rules from ${
|
|
13556
|
+
description: `List all rules from ${join102(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
|
|
13421
13557
|
parameters: ruleToolSchemas.listRules,
|
|
13422
13558
|
execute: async () => {
|
|
13423
13559
|
const rules = await listRules();
|
|
@@ -13459,7 +13595,7 @@ var ruleTools = {
|
|
|
13459
13595
|
};
|
|
13460
13596
|
|
|
13461
13597
|
// src/mcp/skills.ts
|
|
13462
|
-
import { basename as basename27, dirname as dirname2, join as
|
|
13598
|
+
import { basename as basename27, dirname as dirname2, join as join103 } from "path";
|
|
13463
13599
|
import { z as z49 } from "zod/mini";
|
|
13464
13600
|
var maxSkillSizeBytes = 1024 * 1024;
|
|
13465
13601
|
var maxSkillsCount = 1e3;
|
|
@@ -13483,9 +13619,9 @@ function extractDirName(relativeDirPathFromCwd) {
|
|
|
13483
13619
|
return dirName;
|
|
13484
13620
|
}
|
|
13485
13621
|
async function listSkills() {
|
|
13486
|
-
const skillsDir =
|
|
13622
|
+
const skillsDir = join103(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH);
|
|
13487
13623
|
try {
|
|
13488
|
-
const skillDirPaths = await findFilesByGlobs(
|
|
13624
|
+
const skillDirPaths = await findFilesByGlobs(join103(skillsDir, "*"), { type: "dir" });
|
|
13489
13625
|
const skills = await Promise.all(
|
|
13490
13626
|
skillDirPaths.map(async (dirPath) => {
|
|
13491
13627
|
const dirName = basename27(dirPath);
|
|
@@ -13496,7 +13632,7 @@ async function listSkills() {
|
|
|
13496
13632
|
});
|
|
13497
13633
|
const frontmatter = skill.getFrontmatter();
|
|
13498
13634
|
return {
|
|
13499
|
-
relativeDirPathFromCwd:
|
|
13635
|
+
relativeDirPathFromCwd: join103(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
|
|
13500
13636
|
frontmatter
|
|
13501
13637
|
};
|
|
13502
13638
|
} catch (error) {
|
|
@@ -13522,7 +13658,7 @@ async function getSkill({ relativeDirPathFromCwd }) {
|
|
|
13522
13658
|
dirName
|
|
13523
13659
|
});
|
|
13524
13660
|
return {
|
|
13525
|
-
relativeDirPathFromCwd:
|
|
13661
|
+
relativeDirPathFromCwd: join103(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
|
|
13526
13662
|
frontmatter: skill.getFrontmatter(),
|
|
13527
13663
|
body: skill.getBody(),
|
|
13528
13664
|
otherFiles: skill.getOtherFiles().map(aiDirFileToMcpSkillFile)
|
|
@@ -13556,7 +13692,7 @@ async function putSkill({
|
|
|
13556
13692
|
try {
|
|
13557
13693
|
const existingSkills = await listSkills();
|
|
13558
13694
|
const isUpdate = existingSkills.some(
|
|
13559
|
-
(skill2) => skill2.relativeDirPathFromCwd ===
|
|
13695
|
+
(skill2) => skill2.relativeDirPathFromCwd === join103(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
|
|
13560
13696
|
);
|
|
13561
13697
|
if (!isUpdate && existingSkills.length >= maxSkillsCount) {
|
|
13562
13698
|
throw new Error(`Maximum number of skills (${maxSkillsCount}) reached`);
|
|
@@ -13571,9 +13707,9 @@ async function putSkill({
|
|
|
13571
13707
|
otherFiles: aiDirFiles,
|
|
13572
13708
|
validate: true
|
|
13573
13709
|
});
|
|
13574
|
-
const skillDirPath =
|
|
13710
|
+
const skillDirPath = join103(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
|
|
13575
13711
|
await ensureDir(skillDirPath);
|
|
13576
|
-
const skillFilePath =
|
|
13712
|
+
const skillFilePath = join103(skillDirPath, SKILL_FILE_NAME);
|
|
13577
13713
|
const skillFileContent = stringifyFrontmatter(body, frontmatter);
|
|
13578
13714
|
await writeFileContent(skillFilePath, skillFileContent);
|
|
13579
13715
|
for (const file of otherFiles) {
|
|
@@ -13581,15 +13717,15 @@ async function putSkill({
|
|
|
13581
13717
|
relativePath: file.name,
|
|
13582
13718
|
intendedRootDir: skillDirPath
|
|
13583
13719
|
});
|
|
13584
|
-
const filePath =
|
|
13585
|
-
const fileDir =
|
|
13720
|
+
const filePath = join103(skillDirPath, file.name);
|
|
13721
|
+
const fileDir = join103(skillDirPath, dirname2(file.name));
|
|
13586
13722
|
if (fileDir !== skillDirPath) {
|
|
13587
13723
|
await ensureDir(fileDir);
|
|
13588
13724
|
}
|
|
13589
13725
|
await writeFileContent(filePath, file.body);
|
|
13590
13726
|
}
|
|
13591
13727
|
return {
|
|
13592
|
-
relativeDirPathFromCwd:
|
|
13728
|
+
relativeDirPathFromCwd: join103(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
|
|
13593
13729
|
frontmatter: skill.getFrontmatter(),
|
|
13594
13730
|
body: skill.getBody(),
|
|
13595
13731
|
otherFiles: skill.getOtherFiles().map(aiDirFileToMcpSkillFile)
|
|
@@ -13611,13 +13747,13 @@ async function deleteSkill({
|
|
|
13611
13747
|
intendedRootDir: process.cwd()
|
|
13612
13748
|
});
|
|
13613
13749
|
const dirName = extractDirName(relativeDirPathFromCwd);
|
|
13614
|
-
const skillDirPath =
|
|
13750
|
+
const skillDirPath = join103(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
|
|
13615
13751
|
try {
|
|
13616
13752
|
if (await directoryExists(skillDirPath)) {
|
|
13617
13753
|
await removeDirectory(skillDirPath);
|
|
13618
13754
|
}
|
|
13619
13755
|
return {
|
|
13620
|
-
relativeDirPathFromCwd:
|
|
13756
|
+
relativeDirPathFromCwd: join103(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
|
|
13621
13757
|
};
|
|
13622
13758
|
} catch (error) {
|
|
13623
13759
|
throw new Error(
|
|
@@ -13650,7 +13786,7 @@ var skillToolSchemas = {
|
|
|
13650
13786
|
var skillTools = {
|
|
13651
13787
|
listSkills: {
|
|
13652
13788
|
name: "listSkills",
|
|
13653
|
-
description: `List all skills from ${
|
|
13789
|
+
description: `List all skills from ${join103(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "*", SKILL_FILE_NAME)} with their frontmatter.`,
|
|
13654
13790
|
parameters: skillToolSchemas.listSkills,
|
|
13655
13791
|
execute: async () => {
|
|
13656
13792
|
const skills = await listSkills();
|
|
@@ -13693,12 +13829,12 @@ var skillTools = {
|
|
|
13693
13829
|
};
|
|
13694
13830
|
|
|
13695
13831
|
// src/mcp/subagents.ts
|
|
13696
|
-
import { basename as basename28, join as
|
|
13832
|
+
import { basename as basename28, join as join104 } from "path";
|
|
13697
13833
|
import { z as z50 } from "zod/mini";
|
|
13698
13834
|
var maxSubagentSizeBytes = 1024 * 1024;
|
|
13699
13835
|
var maxSubagentsCount = 1e3;
|
|
13700
13836
|
async function listSubagents() {
|
|
13701
|
-
const subagentsDir =
|
|
13837
|
+
const subagentsDir = join104(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
|
|
13702
13838
|
try {
|
|
13703
13839
|
const files = await listDirectoryFiles(subagentsDir);
|
|
13704
13840
|
const mdFiles = files.filter((file) => file.endsWith(".md"));
|
|
@@ -13711,7 +13847,7 @@ async function listSubagents() {
|
|
|
13711
13847
|
});
|
|
13712
13848
|
const frontmatter = subagent.getFrontmatter();
|
|
13713
13849
|
return {
|
|
13714
|
-
relativePathFromCwd:
|
|
13850
|
+
relativePathFromCwd: join104(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, file),
|
|
13715
13851
|
frontmatter
|
|
13716
13852
|
};
|
|
13717
13853
|
} catch (error) {
|
|
@@ -13740,7 +13876,7 @@ async function getSubagent({ relativePathFromCwd }) {
|
|
|
13740
13876
|
validate: true
|
|
13741
13877
|
});
|
|
13742
13878
|
return {
|
|
13743
|
-
relativePathFromCwd:
|
|
13879
|
+
relativePathFromCwd: join104(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
|
|
13744
13880
|
frontmatter: subagent.getFrontmatter(),
|
|
13745
13881
|
body: subagent.getBody()
|
|
13746
13882
|
};
|
|
@@ -13769,7 +13905,7 @@ async function putSubagent({
|
|
|
13769
13905
|
try {
|
|
13770
13906
|
const existingSubagents = await listSubagents();
|
|
13771
13907
|
const isUpdate = existingSubagents.some(
|
|
13772
|
-
(subagent2) => subagent2.relativePathFromCwd ===
|
|
13908
|
+
(subagent2) => subagent2.relativePathFromCwd === join104(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
|
|
13773
13909
|
);
|
|
13774
13910
|
if (!isUpdate && existingSubagents.length >= maxSubagentsCount) {
|
|
13775
13911
|
throw new Error(`Maximum number of subagents (${maxSubagentsCount}) reached`);
|
|
@@ -13782,11 +13918,11 @@ async function putSubagent({
|
|
|
13782
13918
|
body,
|
|
13783
13919
|
validate: true
|
|
13784
13920
|
});
|
|
13785
|
-
const subagentsDir =
|
|
13921
|
+
const subagentsDir = join104(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
|
|
13786
13922
|
await ensureDir(subagentsDir);
|
|
13787
13923
|
await writeFileContent(subagent.getFilePath(), subagent.getFileContent());
|
|
13788
13924
|
return {
|
|
13789
|
-
relativePathFromCwd:
|
|
13925
|
+
relativePathFromCwd: join104(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
|
|
13790
13926
|
frontmatter: subagent.getFrontmatter(),
|
|
13791
13927
|
body: subagent.getBody()
|
|
13792
13928
|
};
|
|
@@ -13802,11 +13938,11 @@ async function deleteSubagent({ relativePathFromCwd }) {
|
|
|
13802
13938
|
intendedRootDir: process.cwd()
|
|
13803
13939
|
});
|
|
13804
13940
|
const filename = basename28(relativePathFromCwd);
|
|
13805
|
-
const fullPath =
|
|
13941
|
+
const fullPath = join104(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename);
|
|
13806
13942
|
try {
|
|
13807
13943
|
await removeFile(fullPath);
|
|
13808
13944
|
return {
|
|
13809
|
-
relativePathFromCwd:
|
|
13945
|
+
relativePathFromCwd: join104(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
|
|
13810
13946
|
};
|
|
13811
13947
|
} catch (error) {
|
|
13812
13948
|
throw new Error(
|
|
@@ -13834,7 +13970,7 @@ var subagentToolSchemas = {
|
|
|
13834
13970
|
var subagentTools = {
|
|
13835
13971
|
listSubagents: {
|
|
13836
13972
|
name: "listSubagents",
|
|
13837
|
-
description: `List all subagents from ${
|
|
13973
|
+
description: `List all subagents from ${join104(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
|
|
13838
13974
|
parameters: subagentToolSchemas.listSubagents,
|
|
13839
13975
|
execute: async () => {
|
|
13840
13976
|
const subagents = await listSubagents();
|
|
@@ -14085,7 +14221,7 @@ async function mcpCommand({ version }) {
|
|
|
14085
14221
|
}
|
|
14086
14222
|
|
|
14087
14223
|
// src/cli/index.ts
|
|
14088
|
-
var getVersion = () => "5.
|
|
14224
|
+
var getVersion = () => "5.9.1";
|
|
14089
14225
|
var main = async () => {
|
|
14090
14226
|
const program = new Command();
|
|
14091
14227
|
const version = getVersion();
|