rulesync 6.0.0 → 6.1.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 +24 -0
- package/dist/index.cjs +162 -63
- package/dist/index.js +572 -473
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -272,6 +272,30 @@ Example:
|
|
|
272
272
|
}
|
|
273
273
|
```
|
|
274
274
|
|
|
275
|
+
### Local Configuration
|
|
276
|
+
|
|
277
|
+
Rulesync supports a local configuration file (`rulesync.local.jsonc`) for machine-specific or developer-specific settings. This file is automatically added to `.gitignore` by `rulesync gitignore` and should not be committed to the repository.
|
|
278
|
+
|
|
279
|
+
**Configuration Priority** (highest to lowest):
|
|
280
|
+
|
|
281
|
+
1. CLI options
|
|
282
|
+
2. `rulesync.local.jsonc`
|
|
283
|
+
3. `rulesync.jsonc`
|
|
284
|
+
4. Default values
|
|
285
|
+
|
|
286
|
+
Example usage:
|
|
287
|
+
|
|
288
|
+
```jsonc
|
|
289
|
+
// rulesync.local.jsonc (not committed to git)
|
|
290
|
+
{
|
|
291
|
+
"$schema": "https://raw.githubusercontent.com/dyoshikawa/rulesync/refs/heads/main/config-schema.json",
|
|
292
|
+
// Override targets for local development
|
|
293
|
+
"targets": ["claudecode"],
|
|
294
|
+
// Enable verbose output for debugging
|
|
295
|
+
"verbose": true,
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
275
299
|
### Target Order and File Conflicts
|
|
276
300
|
|
|
277
301
|
When multiple targets write to the same output file, **the last target in the array wins**. This is the "last-wins" behavior.
|
package/dist/index.cjs
CHANGED
|
@@ -118,14 +118,29 @@ var logger = new Logger();
|
|
|
118
118
|
|
|
119
119
|
// src/config/config-resolver.ts
|
|
120
120
|
var import_jsonc_parser = require("jsonc-parser");
|
|
121
|
-
var
|
|
121
|
+
var import_node_path3 = require("path");
|
|
122
|
+
|
|
123
|
+
// src/constants/rulesync-paths.ts
|
|
124
|
+
var import_node_path = require("path");
|
|
125
|
+
var RULESYNC_CONFIG_RELATIVE_FILE_PATH = "rulesync.jsonc";
|
|
126
|
+
var RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH = "rulesync.local.jsonc";
|
|
127
|
+
var RULESYNC_RELATIVE_DIR_PATH = ".rulesync";
|
|
128
|
+
var RULESYNC_RULES_RELATIVE_DIR_PATH = (0, import_node_path.join)(RULESYNC_RELATIVE_DIR_PATH, "rules");
|
|
129
|
+
var RULESYNC_COMMANDS_RELATIVE_DIR_PATH = (0, import_node_path.join)(RULESYNC_RELATIVE_DIR_PATH, "commands");
|
|
130
|
+
var RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH = (0, import_node_path.join)(RULESYNC_RELATIVE_DIR_PATH, "subagents");
|
|
131
|
+
var RULESYNC_MCP_RELATIVE_FILE_PATH = (0, import_node_path.join)(RULESYNC_RELATIVE_DIR_PATH, "mcp.json");
|
|
132
|
+
var RULESYNC_AIIGNORE_FILE_NAME = ".aiignore";
|
|
133
|
+
var RULESYNC_AIIGNORE_RELATIVE_FILE_PATH = (0, import_node_path.join)(RULESYNC_RELATIVE_DIR_PATH, ".aiignore");
|
|
134
|
+
var RULESYNC_IGNORE_RELATIVE_FILE_PATH = ".rulesyncignore";
|
|
135
|
+
var RULESYNC_OVERVIEW_FILE_NAME = "overview.md";
|
|
136
|
+
var RULESYNC_SKILLS_RELATIVE_DIR_PATH = (0, import_node_path.join)(RULESYNC_RELATIVE_DIR_PATH, "skills");
|
|
122
137
|
|
|
123
138
|
// src/utils/file.ts
|
|
124
139
|
var import_es_toolkit = require("es-toolkit");
|
|
125
140
|
var import_globby = require("globby");
|
|
126
141
|
var import_promises = require("fs/promises");
|
|
127
142
|
var import_node_os = __toESM(require("os"), 1);
|
|
128
|
-
var
|
|
143
|
+
var import_node_path2 = require("path");
|
|
129
144
|
async function ensureDir(dirPath) {
|
|
130
145
|
try {
|
|
131
146
|
await (0, import_promises.stat)(dirPath);
|
|
@@ -137,7 +152,7 @@ async function readOrInitializeFileContent(filePath, initialContent = "") {
|
|
|
137
152
|
if (await fileExists(filePath)) {
|
|
138
153
|
return await readFileContent(filePath);
|
|
139
154
|
} else {
|
|
140
|
-
await ensureDir((0,
|
|
155
|
+
await ensureDir((0, import_node_path2.dirname)(filePath));
|
|
141
156
|
await writeFileContent(filePath, initialContent);
|
|
142
157
|
return initialContent;
|
|
143
158
|
}
|
|
@@ -150,16 +165,16 @@ function checkPathTraversal({
|
|
|
150
165
|
if (segments.includes("..")) {
|
|
151
166
|
throw new Error(`Path traversal detected: ${relativePath}`);
|
|
152
167
|
}
|
|
153
|
-
const resolved = (0,
|
|
154
|
-
const rel = (0,
|
|
155
|
-
if (rel.startsWith("..") || (0,
|
|
168
|
+
const resolved = (0, import_node_path2.resolve)(intendedRootDir, relativePath);
|
|
169
|
+
const rel = (0, import_node_path2.relative)(intendedRootDir, resolved);
|
|
170
|
+
if (rel.startsWith("..") || (0, import_node_path2.resolve)(resolved) !== resolved) {
|
|
156
171
|
throw new Error(`Path traversal detected: ${relativePath}`);
|
|
157
172
|
}
|
|
158
173
|
}
|
|
159
174
|
function resolvePath(relativePath, baseDir) {
|
|
160
175
|
if (!baseDir) return relativePath;
|
|
161
176
|
checkPathTraversal({ relativePath, intendedRootDir: baseDir });
|
|
162
|
-
return (0,
|
|
177
|
+
return (0, import_node_path2.resolve)(baseDir, relativePath);
|
|
163
178
|
}
|
|
164
179
|
async function directoryExists(dirPath) {
|
|
165
180
|
try {
|
|
@@ -185,7 +200,7 @@ function addTrailingNewline(content) {
|
|
|
185
200
|
}
|
|
186
201
|
async function writeFileContent(filepath, content) {
|
|
187
202
|
logger.debug(`Writing file: ${filepath}`);
|
|
188
|
-
await ensureDir((0,
|
|
203
|
+
await ensureDir((0, import_node_path2.dirname)(filepath));
|
|
189
204
|
await (0, import_promises.writeFile)(filepath, content, "utf-8");
|
|
190
205
|
}
|
|
191
206
|
async function fileExists(filepath) {
|
|
@@ -413,7 +428,7 @@ var getDefaults = () => ({
|
|
|
413
428
|
verbose: false,
|
|
414
429
|
delete: false,
|
|
415
430
|
baseDirs: [process.cwd()],
|
|
416
|
-
configPath:
|
|
431
|
+
configPath: RULESYNC_CONFIG_RELATIVE_FILE_PATH,
|
|
417
432
|
global: false,
|
|
418
433
|
silent: false,
|
|
419
434
|
simulateCommands: false,
|
|
@@ -421,6 +436,36 @@ var getDefaults = () => ({
|
|
|
421
436
|
simulateSkills: false,
|
|
422
437
|
modularMcp: false
|
|
423
438
|
});
|
|
439
|
+
var loadConfigFromFile = async (filePath) => {
|
|
440
|
+
if (!await fileExists(filePath)) {
|
|
441
|
+
return {};
|
|
442
|
+
}
|
|
443
|
+
try {
|
|
444
|
+
const fileContent = await readFileContent(filePath);
|
|
445
|
+
const jsonData = (0, import_jsonc_parser.parse)(fileContent);
|
|
446
|
+
const parsed = ConfigFileSchema.parse(jsonData);
|
|
447
|
+
const { $schema: _schema, ...configParams } = parsed;
|
|
448
|
+
return configParams;
|
|
449
|
+
} catch (error) {
|
|
450
|
+
logger.error(`Failed to load config file "${filePath}": ${formatError(error)}`);
|
|
451
|
+
throw error;
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
var mergeConfigs = (baseConfig, localConfig) => {
|
|
455
|
+
return {
|
|
456
|
+
targets: localConfig.targets ?? baseConfig.targets,
|
|
457
|
+
features: localConfig.features ?? baseConfig.features,
|
|
458
|
+
verbose: localConfig.verbose ?? baseConfig.verbose,
|
|
459
|
+
delete: localConfig.delete ?? baseConfig.delete,
|
|
460
|
+
baseDirs: localConfig.baseDirs ?? baseConfig.baseDirs,
|
|
461
|
+
global: localConfig.global ?? baseConfig.global,
|
|
462
|
+
silent: localConfig.silent ?? baseConfig.silent,
|
|
463
|
+
simulateCommands: localConfig.simulateCommands ?? baseConfig.simulateCommands,
|
|
464
|
+
simulateSubagents: localConfig.simulateSubagents ?? baseConfig.simulateSubagents,
|
|
465
|
+
simulateSkills: localConfig.simulateSkills ?? baseConfig.simulateSkills,
|
|
466
|
+
modularMcp: localConfig.modularMcp ?? baseConfig.modularMcp
|
|
467
|
+
};
|
|
468
|
+
};
|
|
424
469
|
var ConfigResolver = class {
|
|
425
470
|
static async resolve({
|
|
426
471
|
targets,
|
|
@@ -437,19 +482,11 @@ var ConfigResolver = class {
|
|
|
437
482
|
modularMcp
|
|
438
483
|
}) {
|
|
439
484
|
const validatedConfigPath = resolvePath(configPath, process.cwd());
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
const parsed = ConfigFileSchema.parse(jsonData);
|
|
446
|
-
const { $schema: _schema, ...configParams2 } = parsed;
|
|
447
|
-
configByFile = configParams2;
|
|
448
|
-
} catch (error) {
|
|
449
|
-
logger.error(`Failed to load config file: ${formatError(error)}`);
|
|
450
|
-
throw error;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
485
|
+
const baseConfig = await loadConfigFromFile(validatedConfigPath);
|
|
486
|
+
const configDir = (0, import_node_path3.dirname)(validatedConfigPath);
|
|
487
|
+
const localConfigPath = (0, import_node_path3.join)(configDir, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH);
|
|
488
|
+
const localConfig = await loadConfigFromFile(localConfigPath);
|
|
489
|
+
const configByFile = mergeConfigs(baseConfig, localConfig);
|
|
453
490
|
const resolvedGlobal = global ?? configByFile.global ?? getDefaults().global;
|
|
454
491
|
const resolvedSimulateCommands = simulateCommands ?? configByFile.simulateCommands ?? getDefaults().simulateCommands;
|
|
455
492
|
const resolvedSimulateSubagents = simulateSubagents ?? configByFile.simulateSubagents ?? getDefaults().simulateSubagents;
|
|
@@ -480,7 +517,7 @@ function getBaseDirsInLightOfGlobal({
|
|
|
480
517
|
if (global) {
|
|
481
518
|
return [getHomeDirectory()];
|
|
482
519
|
}
|
|
483
|
-
const resolvedBaseDirs = baseDirs.map((baseDir) => (0,
|
|
520
|
+
const resolvedBaseDirs = baseDirs.map((baseDir) => (0, import_node_path3.resolve)(baseDir));
|
|
484
521
|
resolvedBaseDirs.forEach((baseDir) => {
|
|
485
522
|
validateBaseDir(baseDir);
|
|
486
523
|
});
|
|
@@ -491,20 +528,6 @@ function getBaseDirsInLightOfGlobal({
|
|
|
491
528
|
var import_es_toolkit4 = require("es-toolkit");
|
|
492
529
|
var import_node_path98 = require("path");
|
|
493
530
|
|
|
494
|
-
// src/constants/rulesync-paths.ts
|
|
495
|
-
var import_node_path3 = require("path");
|
|
496
|
-
var RULESYNC_CONFIG_RELATIVE_FILE_PATH = "rulesync.jsonc";
|
|
497
|
-
var RULESYNC_RELATIVE_DIR_PATH = ".rulesync";
|
|
498
|
-
var RULESYNC_RULES_RELATIVE_DIR_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, "rules");
|
|
499
|
-
var RULESYNC_COMMANDS_RELATIVE_DIR_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, "commands");
|
|
500
|
-
var RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, "subagents");
|
|
501
|
-
var RULESYNC_MCP_RELATIVE_FILE_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, "mcp.json");
|
|
502
|
-
var RULESYNC_AIIGNORE_FILE_NAME = ".aiignore";
|
|
503
|
-
var RULESYNC_AIIGNORE_RELATIVE_FILE_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, ".aiignore");
|
|
504
|
-
var RULESYNC_IGNORE_RELATIVE_FILE_PATH = ".rulesyncignore";
|
|
505
|
-
var RULESYNC_OVERVIEW_FILE_NAME = "overview.md";
|
|
506
|
-
var RULESYNC_SKILLS_RELATIVE_DIR_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, "skills");
|
|
507
|
-
|
|
508
531
|
// src/features/commands/commands-processor.ts
|
|
509
532
|
var import_node_path19 = require("path");
|
|
510
533
|
var import_mini12 = require("zod/mini");
|
|
@@ -4047,14 +4070,16 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
|
|
|
4047
4070
|
static forDeletion({
|
|
4048
4071
|
baseDir = process.cwd(),
|
|
4049
4072
|
relativeDirPath,
|
|
4050
|
-
relativeFilePath
|
|
4073
|
+
relativeFilePath,
|
|
4074
|
+
global = false
|
|
4051
4075
|
}) {
|
|
4052
4076
|
return new _ClaudecodeMcp({
|
|
4053
4077
|
baseDir,
|
|
4054
4078
|
relativeDirPath,
|
|
4055
4079
|
relativeFilePath,
|
|
4056
4080
|
fileContent: "{}",
|
|
4057
|
-
validate: false
|
|
4081
|
+
validate: false,
|
|
4082
|
+
global
|
|
4058
4083
|
});
|
|
4059
4084
|
}
|
|
4060
4085
|
};
|
|
@@ -4318,6 +4343,46 @@ var CopilotMcp = class _CopilotMcp extends ToolMcp {
|
|
|
4318
4343
|
|
|
4319
4344
|
// src/features/mcp/cursor-mcp.ts
|
|
4320
4345
|
var import_node_path39 = require("path");
|
|
4346
|
+
var CURSOR_ENV_VAR_PATTERN = /\$\{env:([^}]+)\}/g;
|
|
4347
|
+
function isMcpServers(value) {
|
|
4348
|
+
return value !== void 0 && value !== null && typeof value === "object";
|
|
4349
|
+
}
|
|
4350
|
+
function convertEnvFromCursorFormat(mcpServers) {
|
|
4351
|
+
return Object.fromEntries(
|
|
4352
|
+
Object.entries(mcpServers).map(([name, config]) => [
|
|
4353
|
+
name,
|
|
4354
|
+
{
|
|
4355
|
+
...config,
|
|
4356
|
+
...config.env && {
|
|
4357
|
+
env: Object.fromEntries(
|
|
4358
|
+
Object.entries(config.env).map(([k, v]) => [
|
|
4359
|
+
k,
|
|
4360
|
+
v.replace(CURSOR_ENV_VAR_PATTERN, "${$1}")
|
|
4361
|
+
])
|
|
4362
|
+
)
|
|
4363
|
+
}
|
|
4364
|
+
}
|
|
4365
|
+
])
|
|
4366
|
+
);
|
|
4367
|
+
}
|
|
4368
|
+
function convertEnvToCursorFormat(mcpServers) {
|
|
4369
|
+
return Object.fromEntries(
|
|
4370
|
+
Object.entries(mcpServers).map(([name, config]) => [
|
|
4371
|
+
name,
|
|
4372
|
+
{
|
|
4373
|
+
...config,
|
|
4374
|
+
...config.env && {
|
|
4375
|
+
env: Object.fromEntries(
|
|
4376
|
+
Object.entries(config.env).map(([k, v]) => [
|
|
4377
|
+
k,
|
|
4378
|
+
v.replace(/\$\{(?!env:)([^}:]+)\}/g, "${env:$1}")
|
|
4379
|
+
])
|
|
4380
|
+
)
|
|
4381
|
+
}
|
|
4382
|
+
}
|
|
4383
|
+
])
|
|
4384
|
+
);
|
|
4385
|
+
}
|
|
4321
4386
|
var CursorMcp = class _CursorMcp extends ToolMcp {
|
|
4322
4387
|
json;
|
|
4323
4388
|
constructor(params) {
|
|
@@ -4358,8 +4423,10 @@ var CursorMcp = class _CursorMcp extends ToolMcp {
|
|
|
4358
4423
|
validate = true
|
|
4359
4424
|
}) {
|
|
4360
4425
|
const json = rulesyncMcp.getJson();
|
|
4426
|
+
const mcpServers = isMcpServers(json.mcpServers) ? json.mcpServers : {};
|
|
4427
|
+
const transformedServers = convertEnvToCursorFormat(mcpServers);
|
|
4361
4428
|
const cursorConfig = {
|
|
4362
|
-
mcpServers:
|
|
4429
|
+
mcpServers: transformedServers
|
|
4363
4430
|
};
|
|
4364
4431
|
const fileContent = JSON.stringify(cursorConfig, null, 2);
|
|
4365
4432
|
return new _CursorMcp({
|
|
@@ -4371,11 +4438,17 @@ var CursorMcp = class _CursorMcp extends ToolMcp {
|
|
|
4371
4438
|
});
|
|
4372
4439
|
}
|
|
4373
4440
|
toRulesyncMcp() {
|
|
4441
|
+
const mcpServers = isMcpServers(this.json.mcpServers) ? this.json.mcpServers : {};
|
|
4442
|
+
const transformedServers = convertEnvFromCursorFormat(mcpServers);
|
|
4443
|
+
const transformedJson = {
|
|
4444
|
+
...this.json,
|
|
4445
|
+
mcpServers: transformedServers
|
|
4446
|
+
};
|
|
4374
4447
|
return new RulesyncMcp({
|
|
4375
4448
|
baseDir: this.baseDir,
|
|
4376
4449
|
relativeDirPath: this.relativeDirPath,
|
|
4377
4450
|
relativeFilePath: "rulesync.mcp.json",
|
|
4378
|
-
fileContent:
|
|
4451
|
+
fileContent: JSON.stringify(transformedJson),
|
|
4379
4452
|
validate: true
|
|
4380
4453
|
});
|
|
4381
4454
|
}
|
|
@@ -4469,17 +4542,25 @@ var GeminiCliMcp = class _GeminiCliMcp extends ToolMcp {
|
|
|
4469
4542
|
validate() {
|
|
4470
4543
|
return { success: true, error: null };
|
|
4471
4544
|
}
|
|
4545
|
+
/**
|
|
4546
|
+
* settings.json may contain other settings, so it should not be deleted.
|
|
4547
|
+
*/
|
|
4548
|
+
isDeletable() {
|
|
4549
|
+
return false;
|
|
4550
|
+
}
|
|
4472
4551
|
static forDeletion({
|
|
4473
4552
|
baseDir = process.cwd(),
|
|
4474
4553
|
relativeDirPath,
|
|
4475
|
-
relativeFilePath
|
|
4554
|
+
relativeFilePath,
|
|
4555
|
+
global = false
|
|
4476
4556
|
}) {
|
|
4477
4557
|
return new _GeminiCliMcp({
|
|
4478
4558
|
baseDir,
|
|
4479
4559
|
relativeDirPath,
|
|
4480
4560
|
relativeFilePath,
|
|
4481
4561
|
fileContent: "{}",
|
|
4482
|
-
validate: false
|
|
4562
|
+
validate: false,
|
|
4563
|
+
global
|
|
4483
4564
|
});
|
|
4484
4565
|
}
|
|
4485
4566
|
};
|
|
@@ -4883,14 +4964,16 @@ var OpencodeMcp = class _OpencodeMcp extends ToolMcp {
|
|
|
4883
4964
|
static forDeletion({
|
|
4884
4965
|
baseDir = process.cwd(),
|
|
4885
4966
|
relativeDirPath,
|
|
4886
|
-
relativeFilePath
|
|
4967
|
+
relativeFilePath,
|
|
4968
|
+
global = false
|
|
4887
4969
|
}) {
|
|
4888
4970
|
return new _OpencodeMcp({
|
|
4889
4971
|
baseDir,
|
|
4890
4972
|
relativeDirPath,
|
|
4891
4973
|
relativeFilePath,
|
|
4892
4974
|
fileContent: "{}",
|
|
4893
|
-
validate: false
|
|
4975
|
+
validate: false,
|
|
4976
|
+
global
|
|
4894
4977
|
});
|
|
4895
4978
|
}
|
|
4896
4979
|
};
|
|
@@ -9046,11 +9129,10 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
|
|
|
9046
9129
|
agentsmd: result.data.agentsmd,
|
|
9047
9130
|
cursor: result.data.cursor
|
|
9048
9131
|
};
|
|
9049
|
-
const filename = (0, import_node_path75.basename)(filePath);
|
|
9050
9132
|
return new _RulesyncRule({
|
|
9051
9133
|
baseDir: process.cwd(),
|
|
9052
9134
|
relativeDirPath: this.getSettablePaths().recommended.relativeDirPath,
|
|
9053
|
-
relativeFilePath
|
|
9135
|
+
relativeFilePath,
|
|
9054
9136
|
frontmatter: validatedFrontmatter,
|
|
9055
9137
|
body: content.trim(),
|
|
9056
9138
|
validate
|
|
@@ -10590,7 +10672,7 @@ var CursorRule = class _CursorRule extends ToolRule {
|
|
|
10590
10672
|
return new _CursorRule({
|
|
10591
10673
|
baseDir,
|
|
10592
10674
|
relativeDirPath: this.getSettablePaths().nonRoot.relativeDirPath,
|
|
10593
|
-
relativeFilePath
|
|
10675
|
+
relativeFilePath,
|
|
10594
10676
|
frontmatter: result.data,
|
|
10595
10677
|
body: content.trim(),
|
|
10596
10678
|
validate
|
|
@@ -11860,10 +11942,17 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
11860
11942
|
* Load and parse rulesync rule files from .rulesync/rules/ directory
|
|
11861
11943
|
*/
|
|
11862
11944
|
async loadRulesyncFiles() {
|
|
11863
|
-
const
|
|
11945
|
+
const rulesyncBaseDir = (0, import_node_path97.join)(this.baseDir, RULESYNC_RULES_RELATIVE_DIR_PATH);
|
|
11946
|
+
const files = await findFilesByGlobs((0, import_node_path97.join)(rulesyncBaseDir, "**", "*.md"));
|
|
11864
11947
|
logger.debug(`Found ${files.length} rulesync files`);
|
|
11865
11948
|
const rulesyncRules = await Promise.all(
|
|
11866
|
-
files.map((file) =>
|
|
11949
|
+
files.map((file) => {
|
|
11950
|
+
const relativeFilePath = (0, import_node_path97.relative)(rulesyncBaseDir, file);
|
|
11951
|
+
checkPathTraversal({ relativePath: relativeFilePath, intendedRootDir: rulesyncBaseDir });
|
|
11952
|
+
return RulesyncRule.fromFile({
|
|
11953
|
+
relativeFilePath
|
|
11954
|
+
});
|
|
11955
|
+
})
|
|
11867
11956
|
);
|
|
11868
11957
|
const rootRules = rulesyncRules.filter((rule) => rule.getFrontmatter().root);
|
|
11869
11958
|
if (rootRules.length > 1) {
|
|
@@ -11966,27 +12055,35 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
11966
12055
|
if (!settablePaths.nonRoot) {
|
|
11967
12056
|
return [];
|
|
11968
12057
|
}
|
|
12058
|
+
const nonRootBaseDir = (0, import_node_path97.join)(this.baseDir, settablePaths.nonRoot.relativeDirPath);
|
|
11969
12059
|
const nonRootFilePaths = await findFilesByGlobs(
|
|
11970
|
-
(0, import_node_path97.join)(
|
|
12060
|
+
(0, import_node_path97.join)(nonRootBaseDir, "**", `*.${factory.meta.extension}`)
|
|
11971
12061
|
);
|
|
11972
12062
|
if (forDeletion) {
|
|
11973
|
-
return nonRootFilePaths.map(
|
|
11974
|
-
(
|
|
12063
|
+
return nonRootFilePaths.map((filePath) => {
|
|
12064
|
+
const relativeFilePath = (0, import_node_path97.relative)(nonRootBaseDir, filePath);
|
|
12065
|
+
checkPathTraversal({
|
|
12066
|
+
relativePath: relativeFilePath,
|
|
12067
|
+
intendedRootDir: nonRootBaseDir
|
|
12068
|
+
});
|
|
12069
|
+
return factory.class.forDeletion({
|
|
11975
12070
|
baseDir: this.baseDir,
|
|
11976
12071
|
relativeDirPath: settablePaths.nonRoot?.relativeDirPath ?? ".",
|
|
11977
|
-
relativeFilePath
|
|
12072
|
+
relativeFilePath,
|
|
11978
12073
|
global: this.global
|
|
11979
|
-
})
|
|
11980
|
-
).filter((rule) => rule.isDeletable());
|
|
12074
|
+
});
|
|
12075
|
+
}).filter((rule) => rule.isDeletable());
|
|
11981
12076
|
}
|
|
11982
12077
|
return await Promise.all(
|
|
11983
|
-
nonRootFilePaths.map(
|
|
11984
|
-
(
|
|
12078
|
+
nonRootFilePaths.map((filePath) => {
|
|
12079
|
+
const relativeFilePath = (0, import_node_path97.relative)(nonRootBaseDir, filePath);
|
|
12080
|
+
checkPathTraversal({ relativePath: relativeFilePath, intendedRootDir: nonRootBaseDir });
|
|
12081
|
+
return factory.class.fromFile({
|
|
11985
12082
|
baseDir: this.baseDir,
|
|
11986
|
-
relativeFilePath
|
|
12083
|
+
relativeFilePath,
|
|
11987
12084
|
global: this.global
|
|
11988
|
-
})
|
|
11989
|
-
)
|
|
12085
|
+
});
|
|
12086
|
+
})
|
|
11990
12087
|
);
|
|
11991
12088
|
})();
|
|
11992
12089
|
logger.debug(`Found ${nonRootToolRules.length} non-root tool rule files`);
|
|
@@ -12342,7 +12439,7 @@ async function generateCommand(options) {
|
|
|
12342
12439
|
silent: config.getSilent()
|
|
12343
12440
|
});
|
|
12344
12441
|
logger.info("Generating files...");
|
|
12345
|
-
if (!await checkRulesyncDirExists({ baseDir:
|
|
12442
|
+
if (!await checkRulesyncDirExists({ baseDir: process.cwd() })) {
|
|
12346
12443
|
logger.error("\u274C .rulesync directory not found. Run 'rulesync init' first.");
|
|
12347
12444
|
process.exit(1);
|
|
12348
12445
|
}
|
|
@@ -12497,6 +12594,7 @@ var RULESYNC_IGNORE_ENTRIES = [
|
|
|
12497
12594
|
// Others
|
|
12498
12595
|
"**/modular-mcp.json",
|
|
12499
12596
|
".rulesync/rules/*.local.md",
|
|
12597
|
+
"rulesync.local.jsonc",
|
|
12500
12598
|
"!.rulesync/.aiignore"
|
|
12501
12599
|
];
|
|
12502
12600
|
var isRulesyncHeader = (line) => {
|
|
@@ -12778,6 +12876,7 @@ async function createConfigFile() {
|
|
|
12778
12876
|
baseDirs: ["."],
|
|
12779
12877
|
delete: true,
|
|
12780
12878
|
verbose: false,
|
|
12879
|
+
silent: false,
|
|
12781
12880
|
global: false,
|
|
12782
12881
|
simulateCommands: false,
|
|
12783
12882
|
simulateSubagents: false,
|
|
@@ -14193,7 +14292,7 @@ async function mcpCommand({ version }) {
|
|
|
14193
14292
|
}
|
|
14194
14293
|
|
|
14195
14294
|
// src/cli/index.ts
|
|
14196
|
-
var getVersion = () => "6.
|
|
14295
|
+
var getVersion = () => "6.1.1";
|
|
14197
14296
|
var main = async () => {
|
|
14198
14297
|
const program = new import_commander.Command();
|
|
14199
14298
|
const version = getVersion();
|