rulesync 0.36.0 → 0.38.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-AWKMUY5R.js +56 -0
- package/dist/{chunk-YGXGGUBG.mjs → chunk-BEJD7I74.js} +5 -7
- package/dist/{chunk-6PQ4APY4.mjs → chunk-HOVR7QDA.js} +6 -9
- package/dist/{chunk-UNTCJDMQ.mjs → chunk-LQDXGEGC.js} +7 -13
- package/dist/{chunk-QVPQ2X4L.mjs → chunk-SPMMXF7R.js} +11 -10
- package/dist/{chunk-SBYRCTWS.mjs → chunk-VZMUQVX4.js} +11 -10
- package/dist/{chunk-QHXMJZTJ.mjs → chunk-XERXHVPP.js} +6 -6
- package/dist/{claude-O4SRX6VC.mjs → claude-ZBX7NASK.js} +2 -1
- package/dist/{cline-H5JF2OPT.mjs → cline-XP43H6CB.js} +2 -1
- package/dist/{copilot-GCIYHK4Q.mjs → copilot-4O7P53MT.js} +2 -1
- package/dist/{cursor-N75OH6WS.mjs → cursor-HSO7S4D3.js} +2 -1
- package/dist/{geminicli-AGOQ32ZE.mjs → geminicli-UZWXPT2J.js} +2 -1
- package/dist/{index.mjs → index.cjs} +561 -186
- package/dist/index.js +207 -503
- package/dist/{roo-V5YVC222.mjs → roo-JSRLCK7Z.js} +2 -1
- package/package.json +15 -13
- /package/dist/{index.d.mts → index.d.cts} +0 -0
|
@@ -1,29 +1,376 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __esm = (fn, res) => function __init() {
|
|
10
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
|
|
29
|
+
// src/schemas/mcp.ts
|
|
30
|
+
var import_zod, ToolTargetSchema, WildcardTargetSchema, SpecificTargetsSchema, RulesyncTargetsSchema, McpTransportTypeSchema, McpServerBaseSchema, RulesyncMcpServerSchema;
|
|
31
|
+
var init_mcp = __esm({
|
|
32
|
+
"src/schemas/mcp.ts"() {
|
|
33
|
+
"use strict";
|
|
34
|
+
import_zod = require("zod");
|
|
35
|
+
ToolTargetSchema = import_zod.z.enum([
|
|
36
|
+
"copilot",
|
|
37
|
+
"cursor",
|
|
38
|
+
"cline",
|
|
39
|
+
"claudecode",
|
|
40
|
+
"claude",
|
|
41
|
+
"roo",
|
|
42
|
+
"geminicli"
|
|
43
|
+
]);
|
|
44
|
+
WildcardTargetSchema = import_zod.z.tuple([import_zod.z.literal("*")]);
|
|
45
|
+
SpecificTargetsSchema = import_zod.z.array(ToolTargetSchema);
|
|
46
|
+
RulesyncTargetsSchema = import_zod.z.union([SpecificTargetsSchema, WildcardTargetSchema]);
|
|
47
|
+
McpTransportTypeSchema = import_zod.z.enum(["stdio", "sse", "http"]);
|
|
48
|
+
McpServerBaseSchema = import_zod.z.object({
|
|
49
|
+
command: import_zod.z.string().optional(),
|
|
50
|
+
args: import_zod.z.array(import_zod.z.string()).optional(),
|
|
51
|
+
url: import_zod.z.string().optional(),
|
|
52
|
+
httpUrl: import_zod.z.string().optional(),
|
|
53
|
+
env: import_zod.z.record(import_zod.z.string()).optional(),
|
|
54
|
+
disabled: import_zod.z.boolean().optional(),
|
|
55
|
+
networkTimeout: import_zod.z.number().optional(),
|
|
56
|
+
timeout: import_zod.z.number().optional(),
|
|
57
|
+
trust: import_zod.z.boolean().optional(),
|
|
58
|
+
cwd: import_zod.z.string().optional(),
|
|
59
|
+
transport: McpTransportTypeSchema.optional(),
|
|
60
|
+
type: import_zod.z.enum(["sse", "streamable-http"]).optional(),
|
|
61
|
+
alwaysAllow: import_zod.z.array(import_zod.z.string()).optional(),
|
|
62
|
+
tools: import_zod.z.array(import_zod.z.string()).optional()
|
|
63
|
+
});
|
|
64
|
+
RulesyncMcpServerSchema = McpServerBaseSchema.extend({
|
|
65
|
+
rulesyncTargets: RulesyncTargetsSchema.optional()
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// src/utils/mcp-helpers.ts
|
|
71
|
+
function shouldIncludeServer(server, targetTool) {
|
|
72
|
+
if (!server.rulesyncTargets || server.rulesyncTargets.length === 0) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
const parsedTargets = RulesyncTargetsSchema.parse(server.rulesyncTargets);
|
|
76
|
+
if (parsedTargets.length === 1 && parsedTargets[0] === "*") {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
const validatedTool = ToolTargetSchema.parse(targetTool);
|
|
80
|
+
for (const target of parsedTargets) {
|
|
81
|
+
if (target === validatedTool) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
var init_mcp_helpers = __esm({
|
|
88
|
+
"src/utils/mcp-helpers.ts"() {
|
|
89
|
+
"use strict";
|
|
90
|
+
init_mcp();
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// src/generators/mcp/claude.ts
|
|
95
|
+
function generateClaudeMcp(config, _target) {
|
|
96
|
+
const claudeSettings = {
|
|
97
|
+
mcpServers: {}
|
|
98
|
+
};
|
|
99
|
+
const shouldInclude = (server) => {
|
|
100
|
+
return shouldIncludeServer(server, "claude");
|
|
101
|
+
};
|
|
102
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
103
|
+
if (!shouldInclude(server)) continue;
|
|
104
|
+
const claudeServer = {};
|
|
105
|
+
if (server.command) {
|
|
106
|
+
claudeServer.command = server.command;
|
|
107
|
+
if (server.args) claudeServer.args = server.args;
|
|
108
|
+
} else if (server.url || server.httpUrl) {
|
|
109
|
+
const url = server.httpUrl || server.url;
|
|
110
|
+
if (url) {
|
|
111
|
+
claudeServer.url = url;
|
|
112
|
+
}
|
|
113
|
+
if (server.httpUrl) {
|
|
114
|
+
claudeServer.transport = "http";
|
|
115
|
+
} else if (server.transport === "sse") {
|
|
116
|
+
claudeServer.transport = "sse";
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (server.env) {
|
|
120
|
+
claudeServer.env = server.env;
|
|
121
|
+
}
|
|
122
|
+
claudeSettings.mcpServers[serverName] = claudeServer;
|
|
123
|
+
}
|
|
124
|
+
return JSON.stringify(claudeSettings, null, 2);
|
|
125
|
+
}
|
|
126
|
+
var init_claude = __esm({
|
|
127
|
+
"src/generators/mcp/claude.ts"() {
|
|
128
|
+
"use strict";
|
|
129
|
+
init_mcp_helpers();
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// src/generators/mcp/cline.ts
|
|
134
|
+
function generateClineMcp(config, _target) {
|
|
135
|
+
const clineConfig = {
|
|
136
|
+
mcpServers: {}
|
|
137
|
+
};
|
|
138
|
+
const shouldInclude = (server) => {
|
|
139
|
+
return shouldIncludeServer(server, "cline");
|
|
140
|
+
};
|
|
141
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
142
|
+
if (!shouldInclude(server)) continue;
|
|
143
|
+
const clineServer = {};
|
|
144
|
+
if (server.command) {
|
|
145
|
+
clineServer.command = server.command;
|
|
146
|
+
if (server.args) clineServer.args = server.args;
|
|
147
|
+
} else if (server.url) {
|
|
148
|
+
clineServer.url = server.url;
|
|
149
|
+
}
|
|
150
|
+
if (server.env) {
|
|
151
|
+
clineServer.env = server.env;
|
|
152
|
+
}
|
|
153
|
+
if (server.disabled !== void 0) {
|
|
154
|
+
clineServer.disabled = server.disabled;
|
|
155
|
+
}
|
|
156
|
+
if (server.alwaysAllow) {
|
|
157
|
+
clineServer.alwaysAllow = server.alwaysAllow;
|
|
158
|
+
}
|
|
159
|
+
if (server.networkTimeout !== void 0) {
|
|
160
|
+
clineServer.networkTimeout = server.networkTimeout;
|
|
161
|
+
}
|
|
162
|
+
clineConfig.mcpServers[serverName] = clineServer;
|
|
163
|
+
}
|
|
164
|
+
return JSON.stringify(clineConfig, null, 2);
|
|
165
|
+
}
|
|
166
|
+
var init_cline = __esm({
|
|
167
|
+
"src/generators/mcp/cline.ts"() {
|
|
168
|
+
"use strict";
|
|
169
|
+
init_mcp_helpers();
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// src/generators/mcp/copilot.ts
|
|
174
|
+
function generateCopilotMcp(config, target) {
|
|
175
|
+
const servers = {};
|
|
176
|
+
const inputs = [];
|
|
177
|
+
const inputMap = /* @__PURE__ */ new Map();
|
|
178
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
179
|
+
if (!shouldIncludeServer(server, "copilot")) continue;
|
|
180
|
+
const copilotServer = {};
|
|
181
|
+
if (server.command) {
|
|
182
|
+
copilotServer.command = server.command;
|
|
183
|
+
if (server.args) copilotServer.args = server.args;
|
|
184
|
+
} else if (server.url || server.httpUrl) {
|
|
185
|
+
const url = server.httpUrl || server.url;
|
|
186
|
+
if (url) {
|
|
187
|
+
copilotServer.url = url;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (server.env) {
|
|
191
|
+
copilotServer.env = {};
|
|
192
|
+
for (const [key, value] of Object.entries(server.env)) {
|
|
193
|
+
if (target === "editor" && value.includes("SECRET")) {
|
|
194
|
+
const inputId = `${serverName}_${key}`;
|
|
195
|
+
inputMap.set(inputId, value);
|
|
196
|
+
copilotServer.env[key] = `\${input:${inputId}}`;
|
|
197
|
+
inputs.push({
|
|
198
|
+
id: inputId,
|
|
199
|
+
type: "password",
|
|
200
|
+
description: `${key} for ${serverName}`
|
|
201
|
+
});
|
|
202
|
+
} else {
|
|
203
|
+
copilotServer.env[key] = value;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (server.tools) {
|
|
208
|
+
copilotServer.tools = server.tools;
|
|
209
|
+
} else if (server.alwaysAllow) {
|
|
210
|
+
copilotServer.tools = server.alwaysAllow;
|
|
211
|
+
}
|
|
212
|
+
servers[serverName] = copilotServer;
|
|
213
|
+
}
|
|
214
|
+
if (target === "codingAgent") {
|
|
215
|
+
const config2 = { mcpServers: servers };
|
|
216
|
+
return JSON.stringify(config2, null, 2);
|
|
217
|
+
} else {
|
|
218
|
+
const config2 = { servers };
|
|
219
|
+
if (inputs.length > 0) {
|
|
220
|
+
config2.inputs = inputs;
|
|
221
|
+
}
|
|
222
|
+
return JSON.stringify(config2, null, 2);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
var init_copilot = __esm({
|
|
226
|
+
"src/generators/mcp/copilot.ts"() {
|
|
227
|
+
"use strict";
|
|
228
|
+
init_mcp_helpers();
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// src/generators/mcp/cursor.ts
|
|
233
|
+
function generateCursorMcp(config, _target) {
|
|
234
|
+
const cursorConfig = {
|
|
235
|
+
mcpServers: {}
|
|
236
|
+
};
|
|
237
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
238
|
+
if (!shouldIncludeServer(server, "cursor")) continue;
|
|
239
|
+
const cursorServer = {};
|
|
240
|
+
if (server.command) {
|
|
241
|
+
cursorServer.command = server.command;
|
|
242
|
+
if (server.args) cursorServer.args = server.args;
|
|
243
|
+
} else if (server.url || server.httpUrl) {
|
|
244
|
+
const url = server.httpUrl || server.url;
|
|
245
|
+
if (url) {
|
|
246
|
+
cursorServer.url = url;
|
|
247
|
+
}
|
|
248
|
+
if (server.httpUrl || server.transport === "http") {
|
|
249
|
+
cursorServer.type = "streamable-http";
|
|
250
|
+
} else if (server.transport === "sse" || server.type === "sse") {
|
|
251
|
+
cursorServer.type = "sse";
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (server.env) {
|
|
255
|
+
cursorServer.env = server.env;
|
|
256
|
+
}
|
|
257
|
+
if (server.cwd) {
|
|
258
|
+
cursorServer.cwd = server.cwd;
|
|
259
|
+
}
|
|
260
|
+
cursorConfig.mcpServers[serverName] = cursorServer;
|
|
261
|
+
}
|
|
262
|
+
return JSON.stringify(cursorConfig, null, 2);
|
|
263
|
+
}
|
|
264
|
+
var init_cursor = __esm({
|
|
265
|
+
"src/generators/mcp/cursor.ts"() {
|
|
266
|
+
"use strict";
|
|
267
|
+
init_mcp_helpers();
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// src/generators/mcp/geminicli.ts
|
|
272
|
+
function generateGeminiCliMcp(config, _target) {
|
|
273
|
+
const geminiSettings = {
|
|
274
|
+
mcpServers: {}
|
|
275
|
+
};
|
|
276
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
277
|
+
if (!shouldIncludeServer(server, "geminicli")) continue;
|
|
278
|
+
const geminiServer = {};
|
|
279
|
+
if (server.command) {
|
|
280
|
+
geminiServer.command = server.command;
|
|
281
|
+
if (server.args) geminiServer.args = server.args;
|
|
282
|
+
} else if (server.url || server.httpUrl) {
|
|
283
|
+
if (server.httpUrl) {
|
|
284
|
+
geminiServer.httpUrl = server.httpUrl;
|
|
285
|
+
} else if (server.url) {
|
|
286
|
+
geminiServer.url = server.url;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (server.env) {
|
|
290
|
+
geminiServer.env = {};
|
|
291
|
+
for (const [key, value] of Object.entries(server.env)) {
|
|
292
|
+
if (value.startsWith("${") && value.endsWith("}")) {
|
|
293
|
+
geminiServer.env[key] = value;
|
|
294
|
+
} else {
|
|
295
|
+
geminiServer.env[key] = `\${${value}}`;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (server.timeout !== void 0) {
|
|
300
|
+
geminiServer.timeout = server.timeout;
|
|
301
|
+
}
|
|
302
|
+
if (server.trust !== void 0) {
|
|
303
|
+
geminiServer.trust = server.trust;
|
|
304
|
+
}
|
|
305
|
+
geminiSettings.mcpServers[serverName] = geminiServer;
|
|
306
|
+
}
|
|
307
|
+
return JSON.stringify(geminiSettings, null, 2);
|
|
308
|
+
}
|
|
309
|
+
var init_geminicli = __esm({
|
|
310
|
+
"src/generators/mcp/geminicli.ts"() {
|
|
311
|
+
"use strict";
|
|
312
|
+
init_mcp_helpers();
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// src/generators/mcp/roo.ts
|
|
317
|
+
function generateRooMcp(config, _target) {
|
|
318
|
+
const rooConfig = {
|
|
319
|
+
mcpServers: {}
|
|
320
|
+
};
|
|
321
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
322
|
+
if (!shouldIncludeServer(server, "roo")) continue;
|
|
323
|
+
const rooServer = {};
|
|
324
|
+
if (server.command) {
|
|
325
|
+
rooServer.command = server.command;
|
|
326
|
+
if (server.args) rooServer.args = server.args;
|
|
327
|
+
} else if (server.url || server.httpUrl) {
|
|
328
|
+
const url = server.httpUrl || server.url;
|
|
329
|
+
if (url) {
|
|
330
|
+
rooServer.url = url;
|
|
331
|
+
}
|
|
332
|
+
if (server.httpUrl || server.transport === "http") {
|
|
333
|
+
rooServer.type = "streamable-http";
|
|
334
|
+
} else if (server.transport === "sse" || server.type === "sse") {
|
|
335
|
+
rooServer.type = "sse";
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
if (server.env) {
|
|
339
|
+
rooServer.env = {};
|
|
340
|
+
for (const [key, value] of Object.entries(server.env)) {
|
|
341
|
+
if (value.startsWith("${env:") && value.endsWith("}")) {
|
|
342
|
+
rooServer.env[key] = value;
|
|
343
|
+
} else {
|
|
344
|
+
rooServer.env[key] = `\${env:${value}}`;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (server.disabled !== void 0) {
|
|
349
|
+
rooServer.disabled = server.disabled;
|
|
350
|
+
}
|
|
351
|
+
if (server.alwaysAllow) {
|
|
352
|
+
rooServer.alwaysAllow = server.alwaysAllow;
|
|
353
|
+
}
|
|
354
|
+
if (server.networkTimeout !== void 0) {
|
|
355
|
+
rooServer.networkTimeout = Math.max(3e4, Math.min(3e5, server.networkTimeout));
|
|
356
|
+
}
|
|
357
|
+
rooConfig.mcpServers[serverName] = rooServer;
|
|
358
|
+
}
|
|
359
|
+
return JSON.stringify(rooConfig, null, 2);
|
|
360
|
+
}
|
|
361
|
+
var init_roo = __esm({
|
|
362
|
+
"src/generators/mcp/roo.ts"() {
|
|
363
|
+
"use strict";
|
|
364
|
+
init_mcp_helpers();
|
|
365
|
+
}
|
|
366
|
+
});
|
|
20
367
|
|
|
21
368
|
// src/cli/index.ts
|
|
22
|
-
|
|
369
|
+
var import_commander = require("commander");
|
|
23
370
|
|
|
24
371
|
// src/cli/commands/add.ts
|
|
25
|
-
|
|
26
|
-
|
|
372
|
+
var import_promises = require("fs/promises");
|
|
373
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
27
374
|
|
|
28
375
|
// src/utils/config.ts
|
|
29
376
|
function getDefaultConfig() {
|
|
@@ -71,10 +418,10 @@ async function addCommand(filename) {
|
|
|
71
418
|
const config = getDefaultConfig();
|
|
72
419
|
const sanitizedFilename = sanitizeFilename(filename);
|
|
73
420
|
const rulesDir = config.aiRulesDir;
|
|
74
|
-
const filePath =
|
|
75
|
-
await mkdir(rulesDir, { recursive: true });
|
|
421
|
+
const filePath = import_node_path.default.join(rulesDir, `${sanitizedFilename}.md`);
|
|
422
|
+
await (0, import_promises.mkdir)(rulesDir, { recursive: true });
|
|
76
423
|
const template = generateRuleTemplate(sanitizedFilename);
|
|
77
|
-
await writeFile(filePath, template, "utf8");
|
|
424
|
+
await (0, import_promises.writeFile)(filePath, template, "utf8");
|
|
78
425
|
console.log(`\u2705 Created rule file: ${filePath}`);
|
|
79
426
|
console.log(`\u{1F4DD} Edit the file to customize your rules.`);
|
|
80
427
|
} catch (error) {
|
|
@@ -86,21 +433,47 @@ async function addCommand(filename) {
|
|
|
86
433
|
}
|
|
87
434
|
|
|
88
435
|
// src/generators/rules/claudecode.ts
|
|
89
|
-
|
|
436
|
+
var import_node_path5 = require("path");
|
|
90
437
|
|
|
91
438
|
// src/utils/file.ts
|
|
92
|
-
|
|
93
|
-
|
|
439
|
+
var import_promises3 = require("fs/promises");
|
|
440
|
+
var import_node_path4 = require("path");
|
|
441
|
+
|
|
442
|
+
// src/utils/file-ops.ts
|
|
443
|
+
var import_promises2 = require("fs/promises");
|
|
444
|
+
var import_node_path2 = require("path");
|
|
445
|
+
async function ensureDir(dirPath) {
|
|
446
|
+
try {
|
|
447
|
+
await (0, import_promises2.stat)(dirPath);
|
|
448
|
+
} catch {
|
|
449
|
+
await (0, import_promises2.mkdir)(dirPath, { recursive: true });
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
async function readFileContent(filepath) {
|
|
453
|
+
return (0, import_promises2.readFile)(filepath, "utf-8");
|
|
454
|
+
}
|
|
455
|
+
async function writeFileContent(filepath, content) {
|
|
456
|
+
await ensureDir((0, import_node_path2.dirname)(filepath));
|
|
457
|
+
await (0, import_promises2.writeFile)(filepath, content, "utf-8");
|
|
458
|
+
}
|
|
459
|
+
async function fileExists(filepath) {
|
|
460
|
+
try {
|
|
461
|
+
await (0, import_promises2.stat)(filepath);
|
|
462
|
+
return true;
|
|
463
|
+
} catch {
|
|
464
|
+
return false;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
94
467
|
|
|
95
468
|
// src/utils/ignore.ts
|
|
96
|
-
|
|
97
|
-
|
|
469
|
+
var import_node_path3 = require("path");
|
|
470
|
+
var import_micromatch = __toESM(require("micromatch"), 1);
|
|
98
471
|
var cachedIgnorePatterns = null;
|
|
99
472
|
async function loadIgnorePatterns(baseDir = process.cwd()) {
|
|
100
473
|
if (cachedIgnorePatterns) {
|
|
101
474
|
return cachedIgnorePatterns;
|
|
102
475
|
}
|
|
103
|
-
const ignorePath = join(baseDir, ".rulesyncignore");
|
|
476
|
+
const ignorePath = (0, import_node_path3.join)(baseDir, ".rulesyncignore");
|
|
104
477
|
if (!await fileExists(ignorePath)) {
|
|
105
478
|
cachedIgnorePatterns = { patterns: [] };
|
|
106
479
|
return cachedIgnorePatterns;
|
|
@@ -125,12 +498,12 @@ function isFileIgnored(filepath, ignorePatterns) {
|
|
|
125
498
|
}
|
|
126
499
|
const negationPatterns = ignorePatterns.filter((p) => p.startsWith("!"));
|
|
127
500
|
const positivePatterns = ignorePatterns.filter((p) => !p.startsWith("!"));
|
|
128
|
-
const isIgnored = positivePatterns.length > 0 &&
|
|
501
|
+
const isIgnored = positivePatterns.length > 0 && import_micromatch.default.isMatch(filepath, positivePatterns, {
|
|
129
502
|
dot: true
|
|
130
503
|
});
|
|
131
504
|
if (isIgnored && negationPatterns.length > 0) {
|
|
132
505
|
const negationPatternsWithoutPrefix = negationPatterns.map((p) => p.substring(1));
|
|
133
|
-
return !
|
|
506
|
+
return !import_micromatch.default.isMatch(filepath, negationPatternsWithoutPrefix, {
|
|
134
507
|
dot: true
|
|
135
508
|
});
|
|
136
509
|
}
|
|
@@ -144,24 +517,10 @@ function filterIgnoredFiles(files, ignorePatterns) {
|
|
|
144
517
|
}
|
|
145
518
|
|
|
146
519
|
// src/utils/file.ts
|
|
147
|
-
async function ensureDir(dirPath) {
|
|
148
|
-
try {
|
|
149
|
-
await stat(dirPath);
|
|
150
|
-
} catch {
|
|
151
|
-
await mkdir2(dirPath, { recursive: true });
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
async function readFileContent(filepath) {
|
|
155
|
-
return readFile(filepath, "utf-8");
|
|
156
|
-
}
|
|
157
|
-
async function writeFileContent(filepath, content) {
|
|
158
|
-
await ensureDir(dirname(filepath));
|
|
159
|
-
await writeFile2(filepath, content, "utf-8");
|
|
160
|
-
}
|
|
161
520
|
async function findFiles(dir, extension = ".md", ignorePatterns) {
|
|
162
521
|
try {
|
|
163
|
-
const files = await readdir(dir);
|
|
164
|
-
const filtered = files.filter((file) => file.endsWith(extension)).map((file) =>
|
|
522
|
+
const files = await (0, import_promises3.readdir)(dir);
|
|
523
|
+
const filtered = files.filter((file) => file.endsWith(extension)).map((file) => (0, import_node_path4.join)(dir, file));
|
|
165
524
|
if (ignorePatterns && ignorePatterns.length > 0) {
|
|
166
525
|
return filterIgnoredFiles(filtered, ignorePatterns);
|
|
167
526
|
}
|
|
@@ -170,14 +529,6 @@ async function findFiles(dir, extension = ".md", ignorePatterns) {
|
|
|
170
529
|
return [];
|
|
171
530
|
}
|
|
172
531
|
}
|
|
173
|
-
async function fileExists(filepath) {
|
|
174
|
-
try {
|
|
175
|
-
await stat(filepath);
|
|
176
|
-
return true;
|
|
177
|
-
} catch {
|
|
178
|
-
return false;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
532
|
async function removeDirectory(dirPath) {
|
|
182
533
|
const dangerousPaths = [".", "/", "~", "src", "node_modules"];
|
|
183
534
|
if (dangerousPaths.includes(dirPath) || dirPath === "") {
|
|
@@ -186,7 +537,7 @@ async function removeDirectory(dirPath) {
|
|
|
186
537
|
}
|
|
187
538
|
try {
|
|
188
539
|
if (await fileExists(dirPath)) {
|
|
189
|
-
await rm(dirPath, { recursive: true, force: true });
|
|
540
|
+
await (0, import_promises3.rm)(dirPath, { recursive: true, force: true });
|
|
190
541
|
}
|
|
191
542
|
} catch (error) {
|
|
192
543
|
console.warn(`Failed to remove directory ${dirPath}:`, error);
|
|
@@ -195,7 +546,7 @@ async function removeDirectory(dirPath) {
|
|
|
195
546
|
async function removeFile(filepath) {
|
|
196
547
|
try {
|
|
197
548
|
if (await fileExists(filepath)) {
|
|
198
|
-
await rm(filepath);
|
|
549
|
+
await (0, import_promises3.rm)(filepath);
|
|
199
550
|
}
|
|
200
551
|
} catch (error) {
|
|
201
552
|
console.warn(`Failed to remove file ${filepath}:`, error);
|
|
@@ -218,23 +569,23 @@ async function generateClaudecodeConfig(rules, config, baseDir) {
|
|
|
218
569
|
const rootRules = rules.filter((r) => r.frontmatter.root === true);
|
|
219
570
|
const detailRules = rules.filter((r) => r.frontmatter.root === false);
|
|
220
571
|
const claudeMdContent = generateClaudeMarkdown(rootRules, detailRules);
|
|
221
|
-
const claudeOutputDir = baseDir ?
|
|
572
|
+
const claudeOutputDir = baseDir ? (0, import_node_path5.join)(baseDir, config.outputPaths.claudecode) : config.outputPaths.claudecode;
|
|
222
573
|
outputs.push({
|
|
223
574
|
tool: "claudecode",
|
|
224
|
-
filepath:
|
|
575
|
+
filepath: (0, import_node_path5.join)(claudeOutputDir, "CLAUDE.md"),
|
|
225
576
|
content: claudeMdContent
|
|
226
577
|
});
|
|
227
578
|
for (const rule of detailRules) {
|
|
228
579
|
const memoryContent = generateMemoryFile(rule);
|
|
229
580
|
outputs.push({
|
|
230
581
|
tool: "claudecode",
|
|
231
|
-
filepath:
|
|
582
|
+
filepath: (0, import_node_path5.join)(claudeOutputDir, ".claude", "memories", `${rule.filename}.md`),
|
|
232
583
|
content: memoryContent
|
|
233
584
|
});
|
|
234
585
|
}
|
|
235
586
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
236
587
|
if (ignorePatterns.patterns.length > 0) {
|
|
237
|
-
const settingsPath = baseDir ?
|
|
588
|
+
const settingsPath = baseDir ? (0, import_node_path5.join)(baseDir, ".claude", "settings.json") : (0, import_node_path5.join)(".claude", "settings.json");
|
|
238
589
|
await updateClaudeSettings(settingsPath, ignorePatterns.patterns);
|
|
239
590
|
}
|
|
240
591
|
return outputs;
|
|
@@ -271,39 +622,46 @@ async function updateClaudeSettings(settingsPath, ignorePatterns) {
|
|
|
271
622
|
try {
|
|
272
623
|
const content = await readFileContent(settingsPath);
|
|
273
624
|
settings = JSON.parse(content);
|
|
274
|
-
} catch
|
|
625
|
+
} catch {
|
|
275
626
|
console.warn(`Failed to parse existing ${settingsPath}, creating new settings`);
|
|
276
627
|
settings = {};
|
|
277
628
|
}
|
|
278
629
|
}
|
|
279
|
-
if (
|
|
280
|
-
settings
|
|
630
|
+
if (typeof settings !== "object" || settings === null) {
|
|
631
|
+
settings = {};
|
|
632
|
+
}
|
|
633
|
+
const settingsObj = settings;
|
|
634
|
+
if (!settingsObj.permissions || typeof settingsObj.permissions !== "object" || settingsObj.permissions === null) {
|
|
635
|
+
settingsObj.permissions = {};
|
|
281
636
|
}
|
|
282
|
-
|
|
283
|
-
|
|
637
|
+
const permissions = settingsObj.permissions;
|
|
638
|
+
if (!Array.isArray(permissions.deny)) {
|
|
639
|
+
permissions.deny = [];
|
|
284
640
|
}
|
|
285
641
|
const readDenyRules = ignorePatterns.map((pattern) => `Read(${pattern})`);
|
|
286
|
-
|
|
642
|
+
const denyArray = permissions.deny;
|
|
643
|
+
const filteredDeny = denyArray.filter((rule) => {
|
|
644
|
+
if (typeof rule !== "string") return false;
|
|
287
645
|
if (!rule.startsWith("Read(")) return true;
|
|
288
646
|
const match = rule.match(/^Read\((.*)\)$/);
|
|
289
647
|
if (!match) return true;
|
|
290
648
|
return !ignorePatterns.includes(match[1] ?? "");
|
|
291
649
|
});
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
const jsonContent = JSON.stringify(
|
|
650
|
+
filteredDeny.push(...readDenyRules);
|
|
651
|
+
permissions.deny = [...new Set(filteredDeny)];
|
|
652
|
+
const jsonContent = JSON.stringify(settingsObj, null, 2);
|
|
295
653
|
await writeFileContent(settingsPath, jsonContent);
|
|
296
654
|
console.log(`\u2705 Updated Claude Code settings: ${settingsPath}`);
|
|
297
655
|
}
|
|
298
656
|
|
|
299
657
|
// src/generators/rules/cline.ts
|
|
300
|
-
|
|
658
|
+
var import_node_path6 = require("path");
|
|
301
659
|
async function generateClineConfig(rules, config, baseDir) {
|
|
302
660
|
const outputs = [];
|
|
303
661
|
for (const rule of rules) {
|
|
304
662
|
const content = generateClineMarkdown(rule);
|
|
305
|
-
const outputDir = baseDir ?
|
|
306
|
-
const filepath =
|
|
663
|
+
const outputDir = baseDir ? (0, import_node_path6.join)(baseDir, config.outputPaths.cline) : config.outputPaths.cline;
|
|
664
|
+
const filepath = (0, import_node_path6.join)(outputDir, `${rule.filename}.md`);
|
|
307
665
|
outputs.push({
|
|
308
666
|
tool: "cline",
|
|
309
667
|
filepath,
|
|
@@ -312,7 +670,7 @@ async function generateClineConfig(rules, config, baseDir) {
|
|
|
312
670
|
}
|
|
313
671
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
314
672
|
if (ignorePatterns.patterns.length > 0) {
|
|
315
|
-
const clineIgnorePath = baseDir ?
|
|
673
|
+
const clineIgnorePath = baseDir ? (0, import_node_path6.join)(baseDir, ".clineignore") : ".clineignore";
|
|
316
674
|
const clineIgnoreContent = generateClineIgnore(ignorePatterns.patterns);
|
|
317
675
|
outputs.push({
|
|
318
676
|
tool: "cline",
|
|
@@ -336,14 +694,14 @@ function generateClineIgnore(patterns) {
|
|
|
336
694
|
}
|
|
337
695
|
|
|
338
696
|
// src/generators/rules/copilot.ts
|
|
339
|
-
|
|
697
|
+
var import_node_path7 = require("path");
|
|
340
698
|
async function generateCopilotConfig(rules, config, baseDir) {
|
|
341
699
|
const outputs = [];
|
|
342
700
|
for (const rule of rules) {
|
|
343
701
|
const content = generateCopilotMarkdown(rule);
|
|
344
702
|
const baseFilename = rule.filename.replace(/\.md$/, "");
|
|
345
|
-
const outputDir = baseDir ?
|
|
346
|
-
const filepath =
|
|
703
|
+
const outputDir = baseDir ? (0, import_node_path7.join)(baseDir, config.outputPaths.copilot) : config.outputPaths.copilot;
|
|
704
|
+
const filepath = (0, import_node_path7.join)(outputDir, `${baseFilename}.instructions.md`);
|
|
347
705
|
outputs.push({
|
|
348
706
|
tool: "copilot",
|
|
349
707
|
filepath,
|
|
@@ -352,7 +710,7 @@ async function generateCopilotConfig(rules, config, baseDir) {
|
|
|
352
710
|
}
|
|
353
711
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
354
712
|
if (ignorePatterns.patterns.length > 0) {
|
|
355
|
-
const copilotIgnorePath = baseDir ?
|
|
713
|
+
const copilotIgnorePath = baseDir ? (0, import_node_path7.join)(baseDir, ".copilotignore") : ".copilotignore";
|
|
356
714
|
const copilotIgnoreContent = generateCopilotIgnore(ignorePatterns.patterns);
|
|
357
715
|
outputs.push({
|
|
358
716
|
tool: "copilot",
|
|
@@ -388,13 +746,13 @@ function generateCopilotIgnore(patterns) {
|
|
|
388
746
|
}
|
|
389
747
|
|
|
390
748
|
// src/generators/rules/cursor.ts
|
|
391
|
-
|
|
749
|
+
var import_node_path8 = require("path");
|
|
392
750
|
async function generateCursorConfig(rules, config, baseDir) {
|
|
393
751
|
const outputs = [];
|
|
394
752
|
for (const rule of rules) {
|
|
395
753
|
const content = generateCursorMarkdown(rule);
|
|
396
|
-
const outputDir = baseDir ?
|
|
397
|
-
const filepath =
|
|
754
|
+
const outputDir = baseDir ? (0, import_node_path8.join)(baseDir, config.outputPaths.cursor) : config.outputPaths.cursor;
|
|
755
|
+
const filepath = (0, import_node_path8.join)(outputDir, `${rule.filename}.mdc`);
|
|
398
756
|
outputs.push({
|
|
399
757
|
tool: "cursor",
|
|
400
758
|
filepath,
|
|
@@ -403,7 +761,7 @@ async function generateCursorConfig(rules, config, baseDir) {
|
|
|
403
761
|
}
|
|
404
762
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
405
763
|
if (ignorePatterns.patterns.length > 0) {
|
|
406
|
-
const cursorIgnorePath = baseDir ?
|
|
764
|
+
const cursorIgnorePath = baseDir ? (0, import_node_path8.join)(baseDir, ".cursorignore") : ".cursorignore";
|
|
407
765
|
const cursorIgnoreContent = generateCursorIgnore(ignorePatterns.patterns);
|
|
408
766
|
outputs.push({
|
|
409
767
|
tool: "cursor",
|
|
@@ -444,15 +802,15 @@ function generateCursorIgnore(patterns) {
|
|
|
444
802
|
}
|
|
445
803
|
|
|
446
804
|
// src/generators/rules/geminicli.ts
|
|
447
|
-
|
|
805
|
+
var import_node_path9 = require("path");
|
|
448
806
|
async function generateGeminiConfig(rules, config, baseDir) {
|
|
449
807
|
const outputs = [];
|
|
450
808
|
const rootRule = rules.find((rule) => rule.frontmatter.root === true);
|
|
451
809
|
const memoryRules = rules.filter((rule) => rule.frontmatter.root === false);
|
|
452
810
|
for (const rule of memoryRules) {
|
|
453
811
|
const content = generateGeminiMemoryMarkdown(rule);
|
|
454
|
-
const outputDir = baseDir ?
|
|
455
|
-
const filepath =
|
|
812
|
+
const outputDir = baseDir ? (0, import_node_path9.join)(baseDir, config.outputPaths.geminicli) : config.outputPaths.geminicli;
|
|
813
|
+
const filepath = (0, import_node_path9.join)(outputDir, `${rule.filename}.md`);
|
|
456
814
|
outputs.push({
|
|
457
815
|
tool: "geminicli",
|
|
458
816
|
filepath,
|
|
@@ -460,7 +818,7 @@ async function generateGeminiConfig(rules, config, baseDir) {
|
|
|
460
818
|
});
|
|
461
819
|
}
|
|
462
820
|
const rootContent = generateGeminiRootMarkdown(rootRule, memoryRules, baseDir);
|
|
463
|
-
const rootFilepath = baseDir ?
|
|
821
|
+
const rootFilepath = baseDir ? (0, import_node_path9.join)(baseDir, "GEMINI.md") : "GEMINI.md";
|
|
464
822
|
outputs.push({
|
|
465
823
|
tool: "geminicli",
|
|
466
824
|
filepath: rootFilepath,
|
|
@@ -468,7 +826,7 @@ async function generateGeminiConfig(rules, config, baseDir) {
|
|
|
468
826
|
});
|
|
469
827
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
470
828
|
if (ignorePatterns.patterns.length > 0) {
|
|
471
|
-
const aiexcludePath = baseDir ?
|
|
829
|
+
const aiexcludePath = baseDir ? (0, import_node_path9.join)(baseDir, ".aiexclude") : ".aiexclude";
|
|
472
830
|
const aiexcludeContent = generateAiexclude(ignorePatterns.patterns);
|
|
473
831
|
outputs.push({
|
|
474
832
|
tool: "geminicli",
|
|
@@ -516,13 +874,13 @@ function generateAiexclude(patterns) {
|
|
|
516
874
|
}
|
|
517
875
|
|
|
518
876
|
// src/generators/rules/roo.ts
|
|
519
|
-
|
|
877
|
+
var import_node_path10 = require("path");
|
|
520
878
|
async function generateRooConfig(rules, config, baseDir) {
|
|
521
879
|
const outputs = [];
|
|
522
880
|
for (const rule of rules) {
|
|
523
881
|
const content = generateRooMarkdown(rule);
|
|
524
|
-
const outputDir = baseDir ?
|
|
525
|
-
const filepath =
|
|
882
|
+
const outputDir = baseDir ? (0, import_node_path10.join)(baseDir, config.outputPaths.roo) : config.outputPaths.roo;
|
|
883
|
+
const filepath = (0, import_node_path10.join)(outputDir, `${rule.filename}.md`);
|
|
526
884
|
outputs.push({
|
|
527
885
|
tool: "roo",
|
|
528
886
|
filepath,
|
|
@@ -531,7 +889,7 @@ async function generateRooConfig(rules, config, baseDir) {
|
|
|
531
889
|
}
|
|
532
890
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
533
891
|
if (ignorePatterns.patterns.length > 0) {
|
|
534
|
-
const rooIgnorePath = baseDir ?
|
|
892
|
+
const rooIgnorePath = baseDir ? (0, import_node_path10.join)(baseDir, ".rooignore") : ".rooignore";
|
|
535
893
|
const rooIgnoreContent = generateRooIgnore(ignorePatterns.patterns);
|
|
536
894
|
outputs.push({
|
|
537
895
|
tool: "roo",
|
|
@@ -604,8 +962,8 @@ async function generateForTool(tool, rules, config, baseDir) {
|
|
|
604
962
|
}
|
|
605
963
|
|
|
606
964
|
// src/core/parser.ts
|
|
607
|
-
|
|
608
|
-
|
|
965
|
+
var import_node_path11 = require("path");
|
|
966
|
+
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
609
967
|
async function parseRulesFromDirectory(aiRulesDir) {
|
|
610
968
|
const ignorePatterns = await loadIgnorePatterns();
|
|
611
969
|
const ruleFiles = await findFiles(aiRulesDir, ".md", ignorePatterns.patterns);
|
|
@@ -638,10 +996,10 @@ ${errors.join("\n")}`);
|
|
|
638
996
|
}
|
|
639
997
|
async function parseRuleFile(filepath) {
|
|
640
998
|
const content = await readFileContent(filepath);
|
|
641
|
-
const parsed =
|
|
999
|
+
const parsed = (0, import_gray_matter.default)(content);
|
|
642
1000
|
validateFrontmatter(parsed.data, filepath);
|
|
643
1001
|
const frontmatter = parsed.data;
|
|
644
|
-
const filename = basename(filepath, ".md");
|
|
1002
|
+
const filename = (0, import_node_path11.basename)(filepath, ".md");
|
|
645
1003
|
return {
|
|
646
1004
|
frontmatter,
|
|
647
1005
|
content: parsed.content,
|
|
@@ -770,19 +1128,27 @@ async function validateRule(rule) {
|
|
|
770
1128
|
}
|
|
771
1129
|
|
|
772
1130
|
// src/core/mcp-generator.ts
|
|
773
|
-
|
|
774
|
-
|
|
1131
|
+
var import_node_os = __toESM(require("os"), 1);
|
|
1132
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
1133
|
+
|
|
1134
|
+
// src/generators/mcp/index.ts
|
|
1135
|
+
init_claude();
|
|
1136
|
+
init_cline();
|
|
1137
|
+
init_copilot();
|
|
1138
|
+
init_cursor();
|
|
1139
|
+
init_geminicli();
|
|
1140
|
+
init_roo();
|
|
775
1141
|
|
|
776
1142
|
// src/core/mcp-parser.ts
|
|
777
|
-
|
|
778
|
-
|
|
1143
|
+
var import_node_fs = __toESM(require("fs"), 1);
|
|
1144
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
779
1145
|
function parseMcpConfig(projectRoot) {
|
|
780
|
-
const mcpPath =
|
|
781
|
-
if (!
|
|
1146
|
+
const mcpPath = import_node_path12.default.join(projectRoot, ".rulesync", ".mcp.json");
|
|
1147
|
+
if (!import_node_fs.default.existsSync(mcpPath)) {
|
|
782
1148
|
return null;
|
|
783
1149
|
}
|
|
784
1150
|
try {
|
|
785
|
-
const content =
|
|
1151
|
+
const content = import_node_fs.default.readFileSync(mcpPath, "utf-8");
|
|
786
1152
|
const rawConfig = JSON.parse(content);
|
|
787
1153
|
if (rawConfig.servers && !rawConfig.mcpServers) {
|
|
788
1154
|
rawConfig.mcpServers = rawConfig.servers;
|
|
@@ -813,32 +1179,32 @@ async function generateMcpConfigs(projectRoot, baseDir) {
|
|
|
813
1179
|
const generators = [
|
|
814
1180
|
{
|
|
815
1181
|
tool: "claude-project",
|
|
816
|
-
path:
|
|
1182
|
+
path: import_node_path13.default.join(targetRoot, ".mcp.json"),
|
|
817
1183
|
generate: () => generateClaudeMcp(config, "project")
|
|
818
1184
|
},
|
|
819
1185
|
{
|
|
820
1186
|
tool: "copilot-editor",
|
|
821
|
-
path:
|
|
1187
|
+
path: import_node_path13.default.join(targetRoot, ".vscode", "mcp.json"),
|
|
822
1188
|
generate: () => generateCopilotMcp(config, "editor")
|
|
823
1189
|
},
|
|
824
1190
|
{
|
|
825
1191
|
tool: "cursor-project",
|
|
826
|
-
path:
|
|
1192
|
+
path: import_node_path13.default.join(targetRoot, ".cursor", "mcp.json"),
|
|
827
1193
|
generate: () => generateCursorMcp(config, "project")
|
|
828
1194
|
},
|
|
829
1195
|
{
|
|
830
1196
|
tool: "cline-project",
|
|
831
|
-
path:
|
|
1197
|
+
path: import_node_path13.default.join(targetRoot, ".cline", "mcp.json"),
|
|
832
1198
|
generate: () => generateClineMcp(config, "project")
|
|
833
1199
|
},
|
|
834
1200
|
{
|
|
835
1201
|
tool: "gemini-project",
|
|
836
|
-
path:
|
|
1202
|
+
path: import_node_path13.default.join(targetRoot, ".gemini", "settings.json"),
|
|
837
1203
|
generate: () => generateGeminiCliMcp(config, "project")
|
|
838
1204
|
},
|
|
839
1205
|
{
|
|
840
1206
|
tool: "roo-project",
|
|
841
|
-
path:
|
|
1207
|
+
path: import_node_path13.default.join(targetRoot, ".roo", "mcp.json"),
|
|
842
1208
|
generate: () => generateRooMcp(config, "project")
|
|
843
1209
|
}
|
|
844
1210
|
];
|
|
@@ -846,17 +1212,17 @@ async function generateMcpConfigs(projectRoot, baseDir) {
|
|
|
846
1212
|
generators.push(
|
|
847
1213
|
{
|
|
848
1214
|
tool: "claude-global",
|
|
849
|
-
path:
|
|
1215
|
+
path: import_node_path13.default.join(import_node_os.default.homedir(), ".claude", "settings.json"),
|
|
850
1216
|
generate: () => generateClaudeMcp(config, "global")
|
|
851
1217
|
},
|
|
852
1218
|
{
|
|
853
1219
|
tool: "cursor-global",
|
|
854
|
-
path:
|
|
1220
|
+
path: import_node_path13.default.join(import_node_os.default.homedir(), ".cursor", "mcp.json"),
|
|
855
1221
|
generate: () => generateCursorMcp(config, "global")
|
|
856
1222
|
},
|
|
857
1223
|
{
|
|
858
1224
|
tool: "gemini-global",
|
|
859
|
-
path:
|
|
1225
|
+
path: import_node_path13.default.join(import_node_os.default.homedir(), ".gemini", "settings.json"),
|
|
860
1226
|
generate: () => generateGeminiCliMcp(config, "global")
|
|
861
1227
|
}
|
|
862
1228
|
);
|
|
@@ -1014,10 +1380,10 @@ Generating configurations for base directory: ${baseDir}`);
|
|
|
1014
1380
|
}
|
|
1015
1381
|
|
|
1016
1382
|
// src/cli/commands/gitignore.ts
|
|
1017
|
-
|
|
1018
|
-
|
|
1383
|
+
var import_node_fs2 = require("fs");
|
|
1384
|
+
var import_node_path14 = require("path");
|
|
1019
1385
|
var gitignoreCommand = async () => {
|
|
1020
|
-
const gitignorePath =
|
|
1386
|
+
const gitignorePath = (0, import_node_path14.join)(process.cwd(), ".gitignore");
|
|
1021
1387
|
const rulesFilesToIgnore = [
|
|
1022
1388
|
"# Generated by rulesync - AI tool configuration files",
|
|
1023
1389
|
"**/.github/copilot-instructions.md",
|
|
@@ -1035,6 +1401,7 @@ var gitignoreCommand = async () => {
|
|
|
1035
1401
|
"**/.gemini/memories/",
|
|
1036
1402
|
"**/.aiexclude",
|
|
1037
1403
|
"**/.mcp.json",
|
|
1404
|
+
"!.rulesync/.mcp.json",
|
|
1038
1405
|
"**/.cursor/mcp.json",
|
|
1039
1406
|
"**/.cline/mcp.json",
|
|
1040
1407
|
"**/.vscode/mcp.json",
|
|
@@ -1042,8 +1409,8 @@ var gitignoreCommand = async () => {
|
|
|
1042
1409
|
"**/.roo/mcp.json"
|
|
1043
1410
|
];
|
|
1044
1411
|
let gitignoreContent = "";
|
|
1045
|
-
if (existsSync(gitignorePath)) {
|
|
1046
|
-
gitignoreContent = readFileSync(gitignorePath, "utf-8");
|
|
1412
|
+
if ((0, import_node_fs2.existsSync)(gitignorePath)) {
|
|
1413
|
+
gitignoreContent = (0, import_node_fs2.readFileSync)(gitignorePath, "utf-8");
|
|
1047
1414
|
}
|
|
1048
1415
|
const linesToAdd = [];
|
|
1049
1416
|
for (const rule of rulesFilesToIgnore) {
|
|
@@ -1060,7 +1427,7 @@ var gitignoreCommand = async () => {
|
|
|
1060
1427
|
${linesToAdd.join("\n")}
|
|
1061
1428
|
` : `${linesToAdd.join("\n")}
|
|
1062
1429
|
`;
|
|
1063
|
-
writeFileSync(gitignorePath, newContent);
|
|
1430
|
+
(0, import_node_fs2.writeFileSync)(gitignorePath, newContent);
|
|
1064
1431
|
console.log(`\u2705 .gitignore\u306B${linesToAdd.length}\u500B\u306E\u30EB\u30FC\u30EB\u3092\u8FFD\u52A0\u3057\u307E\u3057\u305F:`);
|
|
1065
1432
|
for (const line of linesToAdd) {
|
|
1066
1433
|
if (!line.startsWith("#")) {
|
|
@@ -1070,17 +1437,17 @@ ${linesToAdd.join("\n")}
|
|
|
1070
1437
|
};
|
|
1071
1438
|
|
|
1072
1439
|
// src/core/importer.ts
|
|
1073
|
-
|
|
1074
|
-
|
|
1440
|
+
var import_node_path21 = require("path");
|
|
1441
|
+
var import_gray_matter4 = __toESM(require("gray-matter"), 1);
|
|
1075
1442
|
|
|
1076
1443
|
// src/parsers/claudecode.ts
|
|
1077
|
-
|
|
1444
|
+
var import_node_path15 = require("path");
|
|
1078
1445
|
async function parseClaudeConfiguration(baseDir = process.cwd()) {
|
|
1079
1446
|
const errors = [];
|
|
1080
1447
|
const rules = [];
|
|
1081
1448
|
let ignorePatterns;
|
|
1082
1449
|
let mcpServers;
|
|
1083
|
-
const claudeFilePath =
|
|
1450
|
+
const claudeFilePath = (0, import_node_path15.join)(baseDir, "CLAUDE.md");
|
|
1084
1451
|
if (!await fileExists(claudeFilePath)) {
|
|
1085
1452
|
errors.push("CLAUDE.md file not found");
|
|
1086
1453
|
return { rules, errors };
|
|
@@ -1091,12 +1458,12 @@ async function parseClaudeConfiguration(baseDir = process.cwd()) {
|
|
|
1091
1458
|
if (mainRule) {
|
|
1092
1459
|
rules.push(mainRule);
|
|
1093
1460
|
}
|
|
1094
|
-
const memoryDir =
|
|
1461
|
+
const memoryDir = (0, import_node_path15.join)(baseDir, ".claude", "memories");
|
|
1095
1462
|
if (await fileExists(memoryDir)) {
|
|
1096
1463
|
const memoryRules = await parseClaudeMemoryFiles(memoryDir);
|
|
1097
1464
|
rules.push(...memoryRules);
|
|
1098
1465
|
}
|
|
1099
|
-
const settingsPath =
|
|
1466
|
+
const settingsPath = (0, import_node_path15.join)(baseDir, ".claude", "settings.json");
|
|
1100
1467
|
if (await fileExists(settingsPath)) {
|
|
1101
1468
|
const settingsResult = await parseClaudeSettings(settingsPath);
|
|
1102
1469
|
if (settingsResult.ignorePatterns) {
|
|
@@ -1153,10 +1520,10 @@ async function parseClaudeMemoryFiles(memoryDir) {
|
|
|
1153
1520
|
const files = await readdir2(memoryDir);
|
|
1154
1521
|
for (const file of files) {
|
|
1155
1522
|
if (file.endsWith(".md")) {
|
|
1156
|
-
const filePath =
|
|
1523
|
+
const filePath = (0, import_node_path15.join)(memoryDir, file);
|
|
1157
1524
|
const content = await readFileContent(filePath);
|
|
1158
1525
|
if (content.trim()) {
|
|
1159
|
-
const filename =
|
|
1526
|
+
const filename = (0, import_node_path15.basename)(file, ".md");
|
|
1160
1527
|
const frontmatter = {
|
|
1161
1528
|
root: false,
|
|
1162
1529
|
targets: ["claudecode"],
|
|
@@ -1172,7 +1539,7 @@ async function parseClaudeMemoryFiles(memoryDir) {
|
|
|
1172
1539
|
}
|
|
1173
1540
|
}
|
|
1174
1541
|
}
|
|
1175
|
-
} catch
|
|
1542
|
+
} catch {
|
|
1176
1543
|
}
|
|
1177
1544
|
return rules;
|
|
1178
1545
|
}
|
|
@@ -1183,17 +1550,25 @@ async function parseClaudeSettings(settingsPath) {
|
|
|
1183
1550
|
try {
|
|
1184
1551
|
const content = await readFileContent(settingsPath);
|
|
1185
1552
|
const settings = JSON.parse(content);
|
|
1186
|
-
if (settings
|
|
1187
|
-
const
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1553
|
+
if (typeof settings === "object" && settings !== null && "permissions" in settings) {
|
|
1554
|
+
const permissions = settings.permissions;
|
|
1555
|
+
if (permissions && "deny" in permissions && Array.isArray(permissions.deny)) {
|
|
1556
|
+
const readPatterns = permissions.deny.filter(
|
|
1557
|
+
(rule) => typeof rule === "string" && rule.startsWith("Read(") && rule.endsWith(")")
|
|
1558
|
+
).map((rule) => {
|
|
1559
|
+
const match = rule.match(/^Read\((.+)\)$/);
|
|
1560
|
+
return match ? match[1] : null;
|
|
1561
|
+
}).filter((pattern) => pattern !== null);
|
|
1562
|
+
if (readPatterns.length > 0) {
|
|
1563
|
+
ignorePatterns = readPatterns;
|
|
1564
|
+
}
|
|
1193
1565
|
}
|
|
1194
1566
|
}
|
|
1195
|
-
if (settings
|
|
1196
|
-
|
|
1567
|
+
if (typeof settings === "object" && settings !== null && "mcpServers" in settings) {
|
|
1568
|
+
const servers = settings.mcpServers;
|
|
1569
|
+
if (servers && typeof servers === "object" && Object.keys(servers).length > 0) {
|
|
1570
|
+
mcpServers = servers;
|
|
1571
|
+
}
|
|
1197
1572
|
}
|
|
1198
1573
|
} catch (error) {
|
|
1199
1574
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -1207,11 +1582,11 @@ async function parseClaudeSettings(settingsPath) {
|
|
|
1207
1582
|
}
|
|
1208
1583
|
|
|
1209
1584
|
// src/parsers/cline.ts
|
|
1210
|
-
|
|
1585
|
+
var import_node_path16 = require("path");
|
|
1211
1586
|
async function parseClineConfiguration(baseDir = process.cwd()) {
|
|
1212
1587
|
const errors = [];
|
|
1213
1588
|
const rules = [];
|
|
1214
|
-
const clineFilePath =
|
|
1589
|
+
const clineFilePath = (0, import_node_path16.join)(baseDir, ".cline", "instructions.md");
|
|
1215
1590
|
if (await fileExists(clineFilePath)) {
|
|
1216
1591
|
try {
|
|
1217
1592
|
const content = await readFileContent(clineFilePath);
|
|
@@ -1234,14 +1609,14 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
|
|
|
1234
1609
|
errors.push(`Failed to parse .cline/instructions.md: ${errorMessage}`);
|
|
1235
1610
|
}
|
|
1236
1611
|
}
|
|
1237
|
-
const clinerulesDirPath =
|
|
1612
|
+
const clinerulesDirPath = (0, import_node_path16.join)(baseDir, ".clinerules");
|
|
1238
1613
|
if (await fileExists(clinerulesDirPath)) {
|
|
1239
1614
|
try {
|
|
1240
1615
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
1241
1616
|
const files = await readdir2(clinerulesDirPath);
|
|
1242
1617
|
for (const file of files) {
|
|
1243
1618
|
if (file.endsWith(".md")) {
|
|
1244
|
-
const filePath =
|
|
1619
|
+
const filePath = (0, import_node_path16.join)(clinerulesDirPath, file);
|
|
1245
1620
|
try {
|
|
1246
1621
|
const content = await readFileContent(filePath);
|
|
1247
1622
|
if (content.trim()) {
|
|
@@ -1277,16 +1652,16 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
|
|
|
1277
1652
|
}
|
|
1278
1653
|
|
|
1279
1654
|
// src/parsers/copilot.ts
|
|
1280
|
-
|
|
1281
|
-
|
|
1655
|
+
var import_node_path17 = require("path");
|
|
1656
|
+
var import_gray_matter2 = __toESM(require("gray-matter"), 1);
|
|
1282
1657
|
async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
1283
1658
|
const errors = [];
|
|
1284
1659
|
const rules = [];
|
|
1285
|
-
const copilotFilePath =
|
|
1660
|
+
const copilotFilePath = (0, import_node_path17.join)(baseDir, ".github", "copilot-instructions.md");
|
|
1286
1661
|
if (await fileExists(copilotFilePath)) {
|
|
1287
1662
|
try {
|
|
1288
1663
|
const rawContent = await readFileContent(copilotFilePath);
|
|
1289
|
-
const parsed =
|
|
1664
|
+
const parsed = (0, import_gray_matter2.default)(rawContent);
|
|
1290
1665
|
const content = parsed.content.trim();
|
|
1291
1666
|
if (content) {
|
|
1292
1667
|
const frontmatter = {
|
|
@@ -1307,19 +1682,19 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
|
1307
1682
|
errors.push(`Failed to parse copilot-instructions.md: ${errorMessage}`);
|
|
1308
1683
|
}
|
|
1309
1684
|
}
|
|
1310
|
-
const instructionsDir =
|
|
1685
|
+
const instructionsDir = (0, import_node_path17.join)(baseDir, ".github", "instructions");
|
|
1311
1686
|
if (await fileExists(instructionsDir)) {
|
|
1312
1687
|
try {
|
|
1313
1688
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
1314
1689
|
const files = await readdir2(instructionsDir);
|
|
1315
1690
|
for (const file of files) {
|
|
1316
1691
|
if (file.endsWith(".instructions.md")) {
|
|
1317
|
-
const filePath =
|
|
1692
|
+
const filePath = (0, import_node_path17.join)(instructionsDir, file);
|
|
1318
1693
|
const rawContent = await readFileContent(filePath);
|
|
1319
|
-
const parsed =
|
|
1694
|
+
const parsed = (0, import_gray_matter2.default)(rawContent);
|
|
1320
1695
|
const content = parsed.content.trim();
|
|
1321
1696
|
if (content) {
|
|
1322
|
-
const filename =
|
|
1697
|
+
const filename = (0, import_node_path17.basename)(file, ".instructions.md");
|
|
1323
1698
|
const frontmatter = {
|
|
1324
1699
|
root: false,
|
|
1325
1700
|
targets: ["copilot"],
|
|
@@ -1349,19 +1724,19 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
|
1349
1724
|
}
|
|
1350
1725
|
|
|
1351
1726
|
// src/parsers/cursor.ts
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1727
|
+
var import_node_path18 = require("path");
|
|
1728
|
+
var import_gray_matter3 = __toESM(require("gray-matter"), 1);
|
|
1729
|
+
var import_js_yaml = require("js-yaml");
|
|
1355
1730
|
var customMatterOptions = {
|
|
1356
1731
|
engines: {
|
|
1357
1732
|
yaml: {
|
|
1358
1733
|
parse: (str) => {
|
|
1359
1734
|
try {
|
|
1360
1735
|
const preprocessed = str.replace(/^(\s*globs:\s*)\*\s*$/gm, '$1"*"');
|
|
1361
|
-
return
|
|
1736
|
+
return (0, import_js_yaml.load)(preprocessed, { schema: import_js_yaml.DEFAULT_SCHEMA });
|
|
1362
1737
|
} catch (error) {
|
|
1363
1738
|
try {
|
|
1364
|
-
return
|
|
1739
|
+
return (0, import_js_yaml.load)(str, { schema: import_js_yaml.FAILSAFE_SCHEMA });
|
|
1365
1740
|
} catch {
|
|
1366
1741
|
throw error;
|
|
1367
1742
|
}
|
|
@@ -1375,11 +1750,11 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
1375
1750
|
const rules = [];
|
|
1376
1751
|
let ignorePatterns;
|
|
1377
1752
|
let mcpServers;
|
|
1378
|
-
const cursorFilePath =
|
|
1753
|
+
const cursorFilePath = (0, import_node_path18.join)(baseDir, ".cursorrules");
|
|
1379
1754
|
if (await fileExists(cursorFilePath)) {
|
|
1380
1755
|
try {
|
|
1381
1756
|
const rawContent = await readFileContent(cursorFilePath);
|
|
1382
|
-
const parsed =
|
|
1757
|
+
const parsed = (0, import_gray_matter3.default)(rawContent, customMatterOptions);
|
|
1383
1758
|
const content = parsed.content.trim();
|
|
1384
1759
|
if (content) {
|
|
1385
1760
|
const frontmatter = {
|
|
@@ -1400,20 +1775,20 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
1400
1775
|
errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
|
|
1401
1776
|
}
|
|
1402
1777
|
}
|
|
1403
|
-
const cursorRulesDir =
|
|
1778
|
+
const cursorRulesDir = (0, import_node_path18.join)(baseDir, ".cursor", "rules");
|
|
1404
1779
|
if (await fileExists(cursorRulesDir)) {
|
|
1405
1780
|
try {
|
|
1406
1781
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
1407
1782
|
const files = await readdir2(cursorRulesDir);
|
|
1408
1783
|
for (const file of files) {
|
|
1409
1784
|
if (file.endsWith(".mdc")) {
|
|
1410
|
-
const filePath =
|
|
1785
|
+
const filePath = (0, import_node_path18.join)(cursorRulesDir, file);
|
|
1411
1786
|
try {
|
|
1412
1787
|
const rawContent = await readFileContent(filePath);
|
|
1413
|
-
const parsed =
|
|
1788
|
+
const parsed = (0, import_gray_matter3.default)(rawContent, customMatterOptions);
|
|
1414
1789
|
const content = parsed.content.trim();
|
|
1415
1790
|
if (content) {
|
|
1416
|
-
const filename =
|
|
1791
|
+
const filename = (0, import_node_path18.basename)(file, ".mdc");
|
|
1417
1792
|
const frontmatter = {
|
|
1418
1793
|
root: false,
|
|
1419
1794
|
targets: ["cursor"],
|
|
@@ -1441,7 +1816,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
1441
1816
|
if (rules.length === 0) {
|
|
1442
1817
|
errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
|
|
1443
1818
|
}
|
|
1444
|
-
const cursorIgnorePath =
|
|
1819
|
+
const cursorIgnorePath = (0, import_node_path18.join)(baseDir, ".cursorignore");
|
|
1445
1820
|
if (await fileExists(cursorIgnorePath)) {
|
|
1446
1821
|
try {
|
|
1447
1822
|
const content = await readFileContent(cursorIgnorePath);
|
|
@@ -1454,7 +1829,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
1454
1829
|
errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
|
|
1455
1830
|
}
|
|
1456
1831
|
}
|
|
1457
|
-
const cursorMcpPath =
|
|
1832
|
+
const cursorMcpPath = (0, import_node_path18.join)(baseDir, ".cursor", "mcp.json");
|
|
1458
1833
|
if (await fileExists(cursorMcpPath)) {
|
|
1459
1834
|
try {
|
|
1460
1835
|
const content = await readFileContent(cursorMcpPath);
|
|
@@ -1476,13 +1851,13 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
1476
1851
|
}
|
|
1477
1852
|
|
|
1478
1853
|
// src/parsers/geminicli.ts
|
|
1479
|
-
|
|
1854
|
+
var import_node_path19 = require("path");
|
|
1480
1855
|
async function parseGeminiConfiguration(baseDir = process.cwd()) {
|
|
1481
1856
|
const errors = [];
|
|
1482
1857
|
const rules = [];
|
|
1483
1858
|
let ignorePatterns;
|
|
1484
1859
|
let mcpServers;
|
|
1485
|
-
const geminiFilePath =
|
|
1860
|
+
const geminiFilePath = (0, import_node_path19.join)(baseDir, "GEMINI.md");
|
|
1486
1861
|
if (!await fileExists(geminiFilePath)) {
|
|
1487
1862
|
errors.push("GEMINI.md file not found");
|
|
1488
1863
|
return { rules, errors };
|
|
@@ -1493,12 +1868,12 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
|
|
|
1493
1868
|
if (mainRule) {
|
|
1494
1869
|
rules.push(mainRule);
|
|
1495
1870
|
}
|
|
1496
|
-
const memoryDir =
|
|
1871
|
+
const memoryDir = (0, import_node_path19.join)(baseDir, ".gemini", "memories");
|
|
1497
1872
|
if (await fileExists(memoryDir)) {
|
|
1498
1873
|
const memoryRules = await parseGeminiMemoryFiles(memoryDir);
|
|
1499
1874
|
rules.push(...memoryRules);
|
|
1500
1875
|
}
|
|
1501
|
-
const settingsPath =
|
|
1876
|
+
const settingsPath = (0, import_node_path19.join)(baseDir, ".gemini", "settings.json");
|
|
1502
1877
|
if (await fileExists(settingsPath)) {
|
|
1503
1878
|
const settingsResult = await parseGeminiSettings(settingsPath);
|
|
1504
1879
|
if (settingsResult.ignorePatterns) {
|
|
@@ -1509,7 +1884,7 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
|
|
|
1509
1884
|
}
|
|
1510
1885
|
errors.push(...settingsResult.errors);
|
|
1511
1886
|
}
|
|
1512
|
-
const aiexcludePath =
|
|
1887
|
+
const aiexcludePath = (0, import_node_path19.join)(baseDir, ".aiexclude");
|
|
1513
1888
|
if (await fileExists(aiexcludePath)) {
|
|
1514
1889
|
const aiexcludePatterns = await parseAiexclude(aiexcludePath);
|
|
1515
1890
|
if (aiexcludePatterns.length > 0) {
|
|
@@ -1562,10 +1937,10 @@ async function parseGeminiMemoryFiles(memoryDir) {
|
|
|
1562
1937
|
const files = await readdir2(memoryDir);
|
|
1563
1938
|
for (const file of files) {
|
|
1564
1939
|
if (file.endsWith(".md")) {
|
|
1565
|
-
const filePath =
|
|
1940
|
+
const filePath = (0, import_node_path19.join)(memoryDir, file);
|
|
1566
1941
|
const content = await readFileContent(filePath);
|
|
1567
1942
|
if (content.trim()) {
|
|
1568
|
-
const filename =
|
|
1943
|
+
const filename = (0, import_node_path19.basename)(file, ".md");
|
|
1569
1944
|
const frontmatter = {
|
|
1570
1945
|
root: false,
|
|
1571
1946
|
targets: ["geminicli"],
|
|
@@ -1581,7 +1956,7 @@ async function parseGeminiMemoryFiles(memoryDir) {
|
|
|
1581
1956
|
}
|
|
1582
1957
|
}
|
|
1583
1958
|
}
|
|
1584
|
-
} catch
|
|
1959
|
+
} catch {
|
|
1585
1960
|
}
|
|
1586
1961
|
return rules;
|
|
1587
1962
|
}
|
|
@@ -1608,17 +1983,17 @@ async function parseAiexclude(aiexcludePath) {
|
|
|
1608
1983
|
const content = await readFileContent(aiexcludePath);
|
|
1609
1984
|
const patterns = content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
1610
1985
|
return patterns;
|
|
1611
|
-
} catch
|
|
1986
|
+
} catch {
|
|
1612
1987
|
return [];
|
|
1613
1988
|
}
|
|
1614
1989
|
}
|
|
1615
1990
|
|
|
1616
1991
|
// src/parsers/roo.ts
|
|
1617
|
-
|
|
1992
|
+
var import_node_path20 = require("path");
|
|
1618
1993
|
async function parseRooConfiguration(baseDir = process.cwd()) {
|
|
1619
1994
|
const errors = [];
|
|
1620
1995
|
const rules = [];
|
|
1621
|
-
const rooFilePath =
|
|
1996
|
+
const rooFilePath = (0, import_node_path20.join)(baseDir, ".roo", "instructions.md");
|
|
1622
1997
|
if (await fileExists(rooFilePath)) {
|
|
1623
1998
|
try {
|
|
1624
1999
|
const content = await readFileContent(rooFilePath);
|
|
@@ -1641,14 +2016,14 @@ async function parseRooConfiguration(baseDir = process.cwd()) {
|
|
|
1641
2016
|
errors.push(`Failed to parse .roo/instructions.md: ${errorMessage}`);
|
|
1642
2017
|
}
|
|
1643
2018
|
}
|
|
1644
|
-
const rooRulesDir =
|
|
2019
|
+
const rooRulesDir = (0, import_node_path20.join)(baseDir, ".roo", "rules");
|
|
1645
2020
|
if (await fileExists(rooRulesDir)) {
|
|
1646
2021
|
try {
|
|
1647
2022
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
1648
2023
|
const files = await readdir2(rooRulesDir);
|
|
1649
2024
|
for (const file of files) {
|
|
1650
2025
|
if (file.endsWith(".md")) {
|
|
1651
|
-
const filePath =
|
|
2026
|
+
const filePath = (0, import_node_path20.join)(rooRulesDir, file);
|
|
1652
2027
|
try {
|
|
1653
2028
|
const content = await readFileContent(filePath);
|
|
1654
2029
|
if (content.trim()) {
|
|
@@ -1749,7 +2124,7 @@ async function importConfiguration(options) {
|
|
|
1749
2124
|
if (rules.length === 0 && !ignorePatterns && !mcpServers) {
|
|
1750
2125
|
return { success: false, rulesCreated: 0, errors };
|
|
1751
2126
|
}
|
|
1752
|
-
const rulesDirPath =
|
|
2127
|
+
const rulesDirPath = (0, import_node_path21.join)(baseDir, rulesDir);
|
|
1753
2128
|
try {
|
|
1754
2129
|
const { mkdir: mkdir3 } = await import("fs/promises");
|
|
1755
2130
|
await mkdir3(rulesDirPath, { recursive: true });
|
|
@@ -1763,7 +2138,7 @@ async function importConfiguration(options) {
|
|
|
1763
2138
|
try {
|
|
1764
2139
|
const baseFilename = `${tool}__${rule.filename}`;
|
|
1765
2140
|
const filename = await generateUniqueFilename(rulesDirPath, baseFilename);
|
|
1766
|
-
const filePath =
|
|
2141
|
+
const filePath = (0, import_node_path21.join)(rulesDirPath, `${filename}.md`);
|
|
1767
2142
|
const content = generateRuleFileContent(rule);
|
|
1768
2143
|
await writeFileContent(filePath, content);
|
|
1769
2144
|
rulesCreated++;
|
|
@@ -1778,7 +2153,7 @@ async function importConfiguration(options) {
|
|
|
1778
2153
|
let ignoreFileCreated = false;
|
|
1779
2154
|
if (ignorePatterns && ignorePatterns.length > 0) {
|
|
1780
2155
|
try {
|
|
1781
|
-
const rulesyncignorePath =
|
|
2156
|
+
const rulesyncignorePath = (0, import_node_path21.join)(baseDir, ".rulesyncignore");
|
|
1782
2157
|
const ignoreContent = `${ignorePatterns.join("\n")}
|
|
1783
2158
|
`;
|
|
1784
2159
|
await writeFileContent(rulesyncignorePath, ignoreContent);
|
|
@@ -1794,7 +2169,7 @@ async function importConfiguration(options) {
|
|
|
1794
2169
|
let mcpFileCreated = false;
|
|
1795
2170
|
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
1796
2171
|
try {
|
|
1797
|
-
const mcpPath =
|
|
2172
|
+
const mcpPath = (0, import_node_path21.join)(baseDir, rulesDir, ".mcp.json");
|
|
1798
2173
|
const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
|
|
1799
2174
|
`;
|
|
1800
2175
|
await writeFileContent(mcpPath, mcpContent);
|
|
@@ -1816,13 +2191,13 @@ async function importConfiguration(options) {
|
|
|
1816
2191
|
};
|
|
1817
2192
|
}
|
|
1818
2193
|
function generateRuleFileContent(rule) {
|
|
1819
|
-
const frontmatter =
|
|
2194
|
+
const frontmatter = import_gray_matter4.default.stringify("", rule.frontmatter);
|
|
1820
2195
|
return frontmatter + rule.content;
|
|
1821
2196
|
}
|
|
1822
2197
|
async function generateUniqueFilename(rulesDir, baseFilename) {
|
|
1823
2198
|
let filename = baseFilename;
|
|
1824
2199
|
let counter = 1;
|
|
1825
|
-
while (await fileExists(
|
|
2200
|
+
while (await fileExists((0, import_node_path21.join)(rulesDir, `${filename}.md`))) {
|
|
1826
2201
|
filename = `${baseFilename}-${counter}`;
|
|
1827
2202
|
counter++;
|
|
1828
2203
|
}
|
|
@@ -1887,7 +2262,7 @@ async function importCommand(options = {}) {
|
|
|
1887
2262
|
}
|
|
1888
2263
|
|
|
1889
2264
|
// src/cli/commands/init.ts
|
|
1890
|
-
|
|
2265
|
+
var import_node_path22 = require("path");
|
|
1891
2266
|
async function initCommand() {
|
|
1892
2267
|
const aiRulesDir = ".rulesync";
|
|
1893
2268
|
console.log("Initializing rulesync...");
|
|
@@ -2017,7 +2392,7 @@ globs: ["src/api/**/*.ts", "src/services/**/*.ts", "src/models/**/*.ts"]
|
|
|
2017
2392
|
}
|
|
2018
2393
|
];
|
|
2019
2394
|
for (const file of sampleFiles) {
|
|
2020
|
-
const filepath =
|
|
2395
|
+
const filepath = (0, import_node_path22.join)(aiRulesDir, file.filename);
|
|
2021
2396
|
if (!await fileExists(filepath)) {
|
|
2022
2397
|
await writeFileContent(filepath, file.content);
|
|
2023
2398
|
console.log(`Created ${filepath}`);
|
|
@@ -2119,13 +2494,13 @@ async function validateCommand() {
|
|
|
2119
2494
|
}
|
|
2120
2495
|
|
|
2121
2496
|
// src/cli/commands/watch.ts
|
|
2122
|
-
|
|
2497
|
+
var import_chokidar = require("chokidar");
|
|
2123
2498
|
async function watchCommand() {
|
|
2124
2499
|
const config = getDefaultConfig();
|
|
2125
2500
|
console.log("\u{1F440} Watching for changes in .rulesync directory...");
|
|
2126
2501
|
console.log("Press Ctrl+C to stop watching");
|
|
2127
2502
|
await generateCommand({ verbose: false });
|
|
2128
|
-
const watcher =
|
|
2503
|
+
const watcher = (0, import_chokidar.watch)(`${config.aiRulesDir}/**/*.md`, {
|
|
2129
2504
|
ignoreInitial: true,
|
|
2130
2505
|
persistent: true
|
|
2131
2506
|
});
|
|
@@ -2159,8 +2534,8 @@ async function watchCommand() {
|
|
|
2159
2534
|
}
|
|
2160
2535
|
|
|
2161
2536
|
// src/cli/index.ts
|
|
2162
|
-
var program = new Command();
|
|
2163
|
-
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.
|
|
2537
|
+
var program = new import_commander.Command();
|
|
2538
|
+
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.38.0");
|
|
2164
2539
|
program.command("init").description("Initialize rulesync in current directory").action(initCommand);
|
|
2165
2540
|
program.command("add <filename>").description("Add a new rule file").action(addCommand);
|
|
2166
2541
|
program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
|