rulesync 0.53.0 → 0.55.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/README.ja.md +186 -23
- package/README.md +101 -25
- package/dist/{augmentcode-ICLQ2NEZ.js → augmentcode-MJYD2Y4S.js} +2 -2
- package/dist/{chunk-TTHBLXOB.js → chunk-3PHMFVXP.js} +1 -1
- package/dist/{chunk-FFW6TGCM.js → chunk-BEPSWIZC.js} +1 -1
- package/dist/chunk-D7XQ4OHK.js +145 -0
- package/dist/{chunk-OPZOVKIL.js → chunk-ORNO5MOO.js} +1 -1
- package/dist/{chunk-Y2XH4E5R.js → chunk-OXKDEZJK.js} +1 -1
- package/dist/{chunk-FNL2KPM3.js → chunk-OY6BYYIX.js} +1 -1
- package/dist/{chunk-YPIFCGAP.js → chunk-PPAQWVXX.js} +1 -1
- package/dist/{chunk-QUJMXHNR.js → chunk-QVPD6ENS.js} +1 -1
- package/dist/{chunk-Y26DXTAT.js → chunk-TJKD6LEW.js} +1 -1
- package/dist/{chunk-HMMTSS5E.js → chunk-UHANRG2O.js} +1 -1
- package/dist/{chunk-IXCMY24P.js → chunk-UZCJNUXO.js} +1 -1
- package/dist/{chunk-USKQYIZ2.js → chunk-VI6SBYFB.js} +1 -0
- package/dist/{claudecode-4XWK2WAY.js → claudecode-CKGUHLRR.js} +3 -3
- package/dist/{cline-MNXOHP77.js → cline-Z5C656VR.js} +3 -3
- package/dist/codexcli-VFUJKSIJ.js +10 -0
- package/dist/{copilot-ARYIWVJ7.js → copilot-4WQS5TA7.js} +2 -2
- package/dist/{cursor-FCS74IAH.js → cursor-HOB2F2V2.js} +2 -2
- package/dist/{geminicli-VOPV6DXZ.js → geminicli-XTMQTIU2.js} +2 -2
- package/dist/index.cjs +608 -171
- package/dist/index.js +554 -183
- package/dist/{junie-A2Y2WZI4.js → junie-AN6CR7DD.js} +2 -2
- package/dist/{kiro-MHIK4UBV.js → kiro-PTUZOHQ2.js} +2 -2
- package/dist/{roo-VG4IUNTE.js → roo-WOMS36KU.js} +2 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -43,6 +43,7 @@ var init_tool_targets = __esm({
|
|
|
43
43
|
"cursor",
|
|
44
44
|
"cline",
|
|
45
45
|
"claudecode",
|
|
46
|
+
"codexcli",
|
|
46
47
|
"roo",
|
|
47
48
|
"geminicli",
|
|
48
49
|
"kiro",
|
|
@@ -241,6 +242,73 @@ var init_cline = __esm({
|
|
|
241
242
|
}
|
|
242
243
|
});
|
|
243
244
|
|
|
245
|
+
// src/generators/mcp/codexcli.ts
|
|
246
|
+
function generateCodexMcp(config) {
|
|
247
|
+
return generateMcpConfig(config, {
|
|
248
|
+
target: "codexcli",
|
|
249
|
+
configPaths: [".codex/mcp-config.json"],
|
|
250
|
+
serverTransform: (server) => {
|
|
251
|
+
const codexServer = {};
|
|
252
|
+
if (server.command) {
|
|
253
|
+
codexServer.command = server.command;
|
|
254
|
+
if (server.args) codexServer.args = server.args;
|
|
255
|
+
codexServer.transport = server.transport || "stdio";
|
|
256
|
+
} else if (server.url || server.httpUrl) {
|
|
257
|
+
const url = server.httpUrl || server.url;
|
|
258
|
+
if (url) {
|
|
259
|
+
codexServer.url = url;
|
|
260
|
+
}
|
|
261
|
+
if (server.httpUrl) {
|
|
262
|
+
codexServer.transport = "http";
|
|
263
|
+
} else if (server.transport === "sse") {
|
|
264
|
+
codexServer.transport = "sse";
|
|
265
|
+
} else if (server.transport === "http") {
|
|
266
|
+
codexServer.transport = "http";
|
|
267
|
+
} else {
|
|
268
|
+
codexServer.transport = "stdio";
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
codexServer.transport = "stdio";
|
|
272
|
+
}
|
|
273
|
+
if (server.env) {
|
|
274
|
+
codexServer.env = { ...server.env };
|
|
275
|
+
if (!codexServer.env.CODEX_DEFAULT_MODEL) {
|
|
276
|
+
codexServer.env.CODEX_DEFAULT_MODEL = "gpt-4o-mini";
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (server.cwd) {
|
|
280
|
+
codexServer.cwd = server.cwd;
|
|
281
|
+
codexServer.workingDirectory = server.cwd;
|
|
282
|
+
}
|
|
283
|
+
if (server.timeout) {
|
|
284
|
+
codexServer.timeout = server.timeout;
|
|
285
|
+
}
|
|
286
|
+
if (server.headers) {
|
|
287
|
+
codexServer.headers = server.headers;
|
|
288
|
+
}
|
|
289
|
+
return codexServer;
|
|
290
|
+
},
|
|
291
|
+
configWrapper: (servers) => ({
|
|
292
|
+
// Configuration format for MCP wrapper servers that expose Codex CLI functionality
|
|
293
|
+
servers,
|
|
294
|
+
_comment: "Configuration for MCP wrapper servers like openai-codex-mcp that integrate with Codex CLI",
|
|
295
|
+
_usage: "This file is intended for use with third-party MCP servers that wrap Codex CLI functionality",
|
|
296
|
+
_examples: {
|
|
297
|
+
python_server: "python -m mcp_server or uvicorn codex_server:app",
|
|
298
|
+
nodejs_server: "node dist/server.js or npm start",
|
|
299
|
+
docker_server: "docker run -i --rm custom/codex-mcp:latest"
|
|
300
|
+
},
|
|
301
|
+
_security_note: "Store API keys in environment variables, not in this configuration file"
|
|
302
|
+
})
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
var init_codexcli = __esm({
|
|
306
|
+
"src/generators/mcp/codexcli.ts"() {
|
|
307
|
+
"use strict";
|
|
308
|
+
init_shared_factory();
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
|
|
244
312
|
// src/generators/mcp/copilot.ts
|
|
245
313
|
function generateCopilotMcp(config, target) {
|
|
246
314
|
const servers = {};
|
|
@@ -558,6 +626,7 @@ function getDefaultConfig() {
|
|
|
558
626
|
cursor: ".cursor/rules",
|
|
559
627
|
cline: ".clinerules",
|
|
560
628
|
claudecode: ".",
|
|
629
|
+
codexcli: ".",
|
|
561
630
|
roo: ".roo/rules",
|
|
562
631
|
geminicli: ".gemini/memories",
|
|
563
632
|
kiro: ".kiro/steering",
|
|
@@ -646,6 +715,7 @@ var OutputPathsSchema = import_mini4.z.object({
|
|
|
646
715
|
cursor: import_mini4.z.optional(import_mini4.z.string()),
|
|
647
716
|
cline: import_mini4.z.optional(import_mini4.z.string()),
|
|
648
717
|
claudecode: import_mini4.z.optional(import_mini4.z.string()),
|
|
718
|
+
codexcli: import_mini4.z.optional(import_mini4.z.string()),
|
|
649
719
|
roo: import_mini4.z.optional(import_mini4.z.string()),
|
|
650
720
|
geminicli: import_mini4.z.optional(import_mini4.z.string()),
|
|
651
721
|
kiro: import_mini4.z.optional(import_mini4.z.string()),
|
|
@@ -709,7 +779,8 @@ var McpServerBaseSchema = import_mini5.z.object({
|
|
|
709
779
|
alwaysAllow: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string())),
|
|
710
780
|
tools: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string())),
|
|
711
781
|
kiroAutoApprove: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string())),
|
|
712
|
-
kiroAutoBlock: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string()))
|
|
782
|
+
kiroAutoBlock: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string())),
|
|
783
|
+
headers: import_mini5.z.optional(import_mini5.z.record(import_mini5.z.string(), import_mini5.z.string()))
|
|
713
784
|
});
|
|
714
785
|
var RulesyncMcpServerSchema = import_mini5.z.extend(McpServerBaseSchema, {
|
|
715
786
|
targets: import_mini5.z.optional(RulesyncTargetsSchema)
|
|
@@ -941,6 +1012,36 @@ function mergeWithCliOptions(config, cliOptions) {
|
|
|
941
1012
|
return merged;
|
|
942
1013
|
}
|
|
943
1014
|
|
|
1015
|
+
// src/utils/error.ts
|
|
1016
|
+
function getErrorMessage(error) {
|
|
1017
|
+
return error instanceof Error ? error.message : String(error);
|
|
1018
|
+
}
|
|
1019
|
+
function formatErrorWithContext(error, context) {
|
|
1020
|
+
const errorMessage = getErrorMessage(error);
|
|
1021
|
+
return `${context}: ${errorMessage}`;
|
|
1022
|
+
}
|
|
1023
|
+
function createErrorResult(error, context) {
|
|
1024
|
+
const errorMessage = context ? formatErrorWithContext(error, context) : getErrorMessage(error);
|
|
1025
|
+
return {
|
|
1026
|
+
success: false,
|
|
1027
|
+
error: errorMessage
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
function createSuccessResult(result) {
|
|
1031
|
+
return {
|
|
1032
|
+
success: true,
|
|
1033
|
+
result
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
async function safeAsyncOperation(operation, errorContext) {
|
|
1037
|
+
try {
|
|
1038
|
+
const result = await operation();
|
|
1039
|
+
return createSuccessResult(result);
|
|
1040
|
+
} catch (error) {
|
|
1041
|
+
return createErrorResult(error, errorContext);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
|
|
944
1045
|
// src/utils/file.ts
|
|
945
1046
|
var import_promises2 = require("fs/promises");
|
|
946
1047
|
var import_node_path = require("path");
|
|
@@ -951,6 +1052,9 @@ async function ensureDir(dirPath) {
|
|
|
951
1052
|
await (0, import_promises2.mkdir)(dirPath, { recursive: true });
|
|
952
1053
|
}
|
|
953
1054
|
}
|
|
1055
|
+
function resolvePath(relativePath, baseDir) {
|
|
1056
|
+
return baseDir ? (0, import_node_path.join)(baseDir, relativePath) : relativePath;
|
|
1057
|
+
}
|
|
954
1058
|
async function readFileContent(filepath) {
|
|
955
1059
|
return (0, import_promises2.readFile)(filepath, "utf-8");
|
|
956
1060
|
}
|
|
@@ -1672,6 +1776,135 @@ var ignoreConfigs = {
|
|
|
1672
1776
|
}
|
|
1673
1777
|
return augmentPatterns;
|
|
1674
1778
|
}
|
|
1779
|
+
},
|
|
1780
|
+
codexcli: {
|
|
1781
|
+
tool: "codexcli",
|
|
1782
|
+
filename: ".codexignore",
|
|
1783
|
+
header: [
|
|
1784
|
+
"# Generated by rulesync - OpenAI Codex CLI ignore file",
|
|
1785
|
+
"# This file controls which files are excluded from Codex CLI's AI context",
|
|
1786
|
+
"# Note: .codexignore is a community-requested feature (GitHub Issue #205)",
|
|
1787
|
+
"# Currently using proposed syntax based on .gitignore patterns"
|
|
1788
|
+
],
|
|
1789
|
+
corePatterns: [
|
|
1790
|
+
"# \u2500\u2500\u2500\u2500\u2500 Security & Credentials (Critical) \u2500\u2500\u2500\u2500\u2500",
|
|
1791
|
+
"# Environment files",
|
|
1792
|
+
".env",
|
|
1793
|
+
".env.*",
|
|
1794
|
+
"!.env.example",
|
|
1795
|
+
"",
|
|
1796
|
+
"# Private keys and certificates",
|
|
1797
|
+
"*.key",
|
|
1798
|
+
"*.pem",
|
|
1799
|
+
"*.p12",
|
|
1800
|
+
"*.pfx",
|
|
1801
|
+
"*.der",
|
|
1802
|
+
"*.crt",
|
|
1803
|
+
"",
|
|
1804
|
+
"# SSH keys",
|
|
1805
|
+
"id_rsa*",
|
|
1806
|
+
"id_dsa*",
|
|
1807
|
+
"*.ppk",
|
|
1808
|
+
"",
|
|
1809
|
+
"# API keys and secrets",
|
|
1810
|
+
"api-keys.json",
|
|
1811
|
+
"credentials.json",
|
|
1812
|
+
"secrets.json",
|
|
1813
|
+
"**/apikeys/",
|
|
1814
|
+
"**/*_token*",
|
|
1815
|
+
"**/*_secret*",
|
|
1816
|
+
"**/*api_key*",
|
|
1817
|
+
"",
|
|
1818
|
+
"# Cloud provider credentials",
|
|
1819
|
+
"aws-credentials.json",
|
|
1820
|
+
"gcp-service-account*.json",
|
|
1821
|
+
"azure-credentials.json",
|
|
1822
|
+
".aws/",
|
|
1823
|
+
"",
|
|
1824
|
+
"# \u2500\u2500\u2500\u2500\u2500 Database & Infrastructure Secrets \u2500\u2500\u2500\u2500\u2500",
|
|
1825
|
+
"# Database configuration",
|
|
1826
|
+
"*.db",
|
|
1827
|
+
"*.sqlite",
|
|
1828
|
+
"*.sqlite3",
|
|
1829
|
+
"database.yml",
|
|
1830
|
+
"**/database/config.*",
|
|
1831
|
+
"",
|
|
1832
|
+
"# Infrastructure as Code secrets",
|
|
1833
|
+
"*.tfstate",
|
|
1834
|
+
"*.tfstate.*",
|
|
1835
|
+
"terraform.tfvars",
|
|
1836
|
+
"secrets.auto.tfvars",
|
|
1837
|
+
".terraform/",
|
|
1838
|
+
"",
|
|
1839
|
+
"# Kubernetes secrets",
|
|
1840
|
+
"**/k8s/**/secret*.yaml",
|
|
1841
|
+
"**/kubernetes/**/secret*.yaml",
|
|
1842
|
+
"",
|
|
1843
|
+
"# \u2500\u2500\u2500\u2500\u2500 Business Sensitive Data \u2500\u2500\u2500\u2500\u2500",
|
|
1844
|
+
"# Sensitive directories",
|
|
1845
|
+
"secrets/",
|
|
1846
|
+
"private/",
|
|
1847
|
+
"confidential/",
|
|
1848
|
+
"internal-docs/",
|
|
1849
|
+
"company-secrets/",
|
|
1850
|
+
"",
|
|
1851
|
+
"# Customer and personal data",
|
|
1852
|
+
"customer-data/",
|
|
1853
|
+
"pii/",
|
|
1854
|
+
"personal-data/",
|
|
1855
|
+
"**/*customer*.csv",
|
|
1856
|
+
"**/*personal*.json",
|
|
1857
|
+
"",
|
|
1858
|
+
"# \u2500\u2500\u2500\u2500\u2500 Build Artifacts & Large Files \u2500\u2500\u2500\u2500\u2500",
|
|
1859
|
+
"# Build outputs (may contain embedded secrets)",
|
|
1860
|
+
"dist/",
|
|
1861
|
+
"build/",
|
|
1862
|
+
"out/",
|
|
1863
|
+
".next/",
|
|
1864
|
+
".nuxt/",
|
|
1865
|
+
"",
|
|
1866
|
+
"# Large files that slow down AI processing",
|
|
1867
|
+
"*.zip",
|
|
1868
|
+
"*.tar.gz",
|
|
1869
|
+
"*.rar",
|
|
1870
|
+
"**/*.{mp4,avi,mov,mkv}",
|
|
1871
|
+
"**/*.{pdf,doc,docx}",
|
|
1872
|
+
"",
|
|
1873
|
+
"# Data files",
|
|
1874
|
+
"*.csv",
|
|
1875
|
+
"*.tsv",
|
|
1876
|
+
"*.xlsx",
|
|
1877
|
+
"data/",
|
|
1878
|
+
"datasets/",
|
|
1879
|
+
"",
|
|
1880
|
+
"# \u2500\u2500\u2500\u2500\u2500 Development Environment \u2500\u2500\u2500\u2500\u2500",
|
|
1881
|
+
"# Personal IDE settings",
|
|
1882
|
+
".vscode/settings.json",
|
|
1883
|
+
".idea/workspace.xml",
|
|
1884
|
+
"",
|
|
1885
|
+
"# Temporary files",
|
|
1886
|
+
"*.swp",
|
|
1887
|
+
"*.swo",
|
|
1888
|
+
"*~",
|
|
1889
|
+
"*.tmp",
|
|
1890
|
+
"",
|
|
1891
|
+
"# Test data with sensitive content",
|
|
1892
|
+
"test-data/sensitive/",
|
|
1893
|
+
"tests/fixtures/real-data/**",
|
|
1894
|
+
"",
|
|
1895
|
+
"# \u2500\u2500\u2500\u2500\u2500 Logs & Runtime Data \u2500\u2500\u2500\u2500\u2500",
|
|
1896
|
+
"*.log",
|
|
1897
|
+
"logs/",
|
|
1898
|
+
".cache/",
|
|
1899
|
+
"",
|
|
1900
|
+
"# \u2500\u2500\u2500\u2500\u2500 Re-include Important Files \u2500\u2500\u2500\u2500\u2500",
|
|
1901
|
+
"# Allow configuration examples and documentation",
|
|
1902
|
+
"!secrets/README.md",
|
|
1903
|
+
"!config/*.example.*",
|
|
1904
|
+
"!docs/**/*.md"
|
|
1905
|
+
],
|
|
1906
|
+
includeCommonPatterns: false,
|
|
1907
|
+
projectPatternsHeader: "# \u2500\u2500\u2500\u2500\u2500 Project-specific patterns from rulesync rules \u2500\u2500\u2500\u2500\u2500"
|
|
1675
1908
|
}
|
|
1676
1909
|
};
|
|
1677
1910
|
|
|
@@ -1749,7 +1982,7 @@ function filterIgnoredFiles(files, ignorePatterns) {
|
|
|
1749
1982
|
|
|
1750
1983
|
// src/generators/rules/shared-helpers.ts
|
|
1751
1984
|
function resolveOutputDir(config, tool, baseDir) {
|
|
1752
|
-
return
|
|
1985
|
+
return resolvePath(config.outputPaths[tool], baseDir);
|
|
1753
1986
|
}
|
|
1754
1987
|
function createOutputsArray() {
|
|
1755
1988
|
return [];
|
|
@@ -1776,7 +2009,7 @@ async function generateRulesConfig(rules, config, generatorConfig, baseDir) {
|
|
|
1776
2009
|
}
|
|
1777
2010
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
1778
2011
|
if (ignorePatterns.patterns.length > 0) {
|
|
1779
|
-
const ignorePath =
|
|
2012
|
+
const ignorePath = resolvePath(generatorConfig.ignoreFileName, baseDir);
|
|
1780
2013
|
const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, generatorConfig.tool);
|
|
1781
2014
|
outputs.push({
|
|
1782
2015
|
tool: generatorConfig.tool,
|
|
@@ -1794,7 +2027,10 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
|
|
|
1794
2027
|
if (generatorConfig.generateDetailContent && generatorConfig.detailSubDir) {
|
|
1795
2028
|
for (const rule of detailRules) {
|
|
1796
2029
|
const content = generatorConfig.generateDetailContent(rule);
|
|
1797
|
-
const filepath =
|
|
2030
|
+
const filepath = resolvePath(
|
|
2031
|
+
(0, import_node_path5.join)(generatorConfig.detailSubDir, `${rule.filename}.md`),
|
|
2032
|
+
baseDir
|
|
2033
|
+
);
|
|
1798
2034
|
outputs.push({
|
|
1799
2035
|
tool: generatorConfig.tool,
|
|
1800
2036
|
filepath,
|
|
@@ -1804,7 +2040,7 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
|
|
|
1804
2040
|
}
|
|
1805
2041
|
if (generatorConfig.generateRootContent && generatorConfig.rootFilePath) {
|
|
1806
2042
|
const rootContent = generatorConfig.generateRootContent(rootRule, detailRules, baseDir);
|
|
1807
|
-
const rootFilepath =
|
|
2043
|
+
const rootFilepath = resolvePath(generatorConfig.rootFilePath, baseDir);
|
|
1808
2044
|
outputs.push({
|
|
1809
2045
|
tool: generatorConfig.tool,
|
|
1810
2046
|
filepath: rootFilepath,
|
|
@@ -1813,7 +2049,7 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
|
|
|
1813
2049
|
}
|
|
1814
2050
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
1815
2051
|
if (ignorePatterns.patterns.length > 0) {
|
|
1816
|
-
const ignorePath =
|
|
2052
|
+
const ignorePath = resolvePath(generatorConfig.ignoreFileName, baseDir);
|
|
1817
2053
|
const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, generatorConfig.tool);
|
|
1818
2054
|
outputs.push({
|
|
1819
2055
|
tool: generatorConfig.tool,
|
|
@@ -1918,30 +2154,22 @@ function generateLegacyGuidelinesFile(allRules) {
|
|
|
1918
2154
|
// src/generators/rules/claudecode.ts
|
|
1919
2155
|
var import_node_path7 = require("path");
|
|
1920
2156
|
async function generateClaudecodeConfig(rules, config, baseDir) {
|
|
1921
|
-
const
|
|
1922
|
-
const rootRules = rules.filter((r) => r.frontmatter.root === true);
|
|
1923
|
-
const detailRules = rules.filter((r) => r.frontmatter.root === false);
|
|
1924
|
-
const claudeMdContent = generateClaudeMarkdown(rootRules, detailRules);
|
|
1925
|
-
const claudeOutputDir = baseDir ? (0, import_node_path7.join)(baseDir, config.outputPaths.claudecode) : config.outputPaths.claudecode;
|
|
1926
|
-
outputs.push({
|
|
2157
|
+
const generatorConfig = {
|
|
1927
2158
|
tool: "claudecode",
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
await updateClaudeSettings(settingsPath, ignorePatterns.patterns);
|
|
1943
|
-
}
|
|
1944
|
-
return outputs;
|
|
2159
|
+
fileExtension: ".md",
|
|
2160
|
+
ignoreFileName: ".aiignore",
|
|
2161
|
+
generateContent: generateMemoryFile,
|
|
2162
|
+
generateRootContent: (rootRule, detailRules) => generateClaudeMarkdown(rootRule ? [rootRule] : [], detailRules),
|
|
2163
|
+
rootFilePath: "CLAUDE.md",
|
|
2164
|
+
generateDetailContent: generateMemoryFile,
|
|
2165
|
+
detailSubDir: ".claude/memories",
|
|
2166
|
+
updateAdditionalConfig: async (ignorePatterns, baseDir2) => {
|
|
2167
|
+
const settingsPath = resolvePath((0, import_node_path7.join)(".claude", "settings.json"), baseDir2);
|
|
2168
|
+
await updateClaudeSettings(settingsPath, ignorePatterns);
|
|
2169
|
+
return [];
|
|
2170
|
+
}
|
|
2171
|
+
};
|
|
2172
|
+
return generateComplexRules(rules, config, generatorConfig, baseDir);
|
|
1945
2173
|
}
|
|
1946
2174
|
function generateClaudeMarkdown(rootRules, detailRules) {
|
|
1947
2175
|
const lines = [];
|
|
@@ -2001,23 +2229,222 @@ async function updateClaudeSettings(settingsPath, ignorePatterns) {
|
|
|
2001
2229
|
console.log(`\u2705 Updated Claude Code settings: ${settingsPath}`);
|
|
2002
2230
|
}
|
|
2003
2231
|
|
|
2232
|
+
// src/generators/rules/generator-registry.ts
|
|
2233
|
+
var import_node_path8 = require("path");
|
|
2234
|
+
var GENERATOR_REGISTRY = {
|
|
2235
|
+
// Simple generators - generate one file per rule
|
|
2236
|
+
cline: {
|
|
2237
|
+
type: "simple",
|
|
2238
|
+
tool: "cline",
|
|
2239
|
+
fileExtension: ".md",
|
|
2240
|
+
ignoreFileName: ".clineignore",
|
|
2241
|
+
generateContent: (rule) => rule.content.trim()
|
|
2242
|
+
},
|
|
2243
|
+
roo: {
|
|
2244
|
+
type: "simple",
|
|
2245
|
+
tool: "roo",
|
|
2246
|
+
fileExtension: ".md",
|
|
2247
|
+
ignoreFileName: ".rooignore",
|
|
2248
|
+
generateContent: (rule) => rule.content.trim()
|
|
2249
|
+
},
|
|
2250
|
+
kiro: {
|
|
2251
|
+
type: "simple",
|
|
2252
|
+
tool: "kiro",
|
|
2253
|
+
fileExtension: ".md",
|
|
2254
|
+
ignoreFileName: ".kiroignore",
|
|
2255
|
+
generateContent: (rule) => rule.content.trim()
|
|
2256
|
+
},
|
|
2257
|
+
augmentcode: {
|
|
2258
|
+
type: "simple",
|
|
2259
|
+
tool: "augmentcode",
|
|
2260
|
+
fileExtension: ".md",
|
|
2261
|
+
ignoreFileName: ".aiignore",
|
|
2262
|
+
generateContent: (rule) => rule.content.trim()
|
|
2263
|
+
},
|
|
2264
|
+
"augmentcode-legacy": {
|
|
2265
|
+
type: "simple",
|
|
2266
|
+
tool: "augmentcode-legacy",
|
|
2267
|
+
fileExtension: ".md",
|
|
2268
|
+
ignoreFileName: ".aiignore",
|
|
2269
|
+
generateContent: (rule) => rule.content.trim()
|
|
2270
|
+
},
|
|
2271
|
+
// Complex generators with custom content formatting
|
|
2272
|
+
copilot: {
|
|
2273
|
+
type: "simple",
|
|
2274
|
+
tool: "copilot",
|
|
2275
|
+
fileExtension: ".instructions.md",
|
|
2276
|
+
ignoreFileName: ".copilotignore",
|
|
2277
|
+
generateContent: (rule) => {
|
|
2278
|
+
const lines = [];
|
|
2279
|
+
lines.push("---");
|
|
2280
|
+
lines.push(`description: "${rule.frontmatter.description}"`);
|
|
2281
|
+
if (rule.frontmatter.globs.length > 0) {
|
|
2282
|
+
lines.push(`applyTo: "${rule.frontmatter.globs.join(", ")}"`);
|
|
2283
|
+
} else {
|
|
2284
|
+
lines.push('applyTo: "**"');
|
|
2285
|
+
}
|
|
2286
|
+
lines.push("---");
|
|
2287
|
+
lines.push(rule.content);
|
|
2288
|
+
return lines.join("\n");
|
|
2289
|
+
},
|
|
2290
|
+
pathResolver: (rule, outputDir) => {
|
|
2291
|
+
const baseFilename = rule.filename.replace(/\.md$/, "");
|
|
2292
|
+
return (0, import_node_path8.join)(outputDir, `${baseFilename}.instructions.md`);
|
|
2293
|
+
}
|
|
2294
|
+
},
|
|
2295
|
+
cursor: {
|
|
2296
|
+
type: "simple",
|
|
2297
|
+
tool: "cursor",
|
|
2298
|
+
fileExtension: ".md",
|
|
2299
|
+
ignoreFileName: ".cursorignore",
|
|
2300
|
+
generateContent: (rule) => rule.content.trim()
|
|
2301
|
+
},
|
|
2302
|
+
codexcli: {
|
|
2303
|
+
type: "simple",
|
|
2304
|
+
tool: "codexcli",
|
|
2305
|
+
fileExtension: ".md",
|
|
2306
|
+
ignoreFileName: ".codexignore",
|
|
2307
|
+
generateContent: (rule) => rule.content.trim()
|
|
2308
|
+
},
|
|
2309
|
+
// Complex generators with root + detail pattern
|
|
2310
|
+
claudecode: {
|
|
2311
|
+
type: "complex",
|
|
2312
|
+
tool: "claudecode",
|
|
2313
|
+
fileExtension: ".md",
|
|
2314
|
+
ignoreFileName: ".aiignore",
|
|
2315
|
+
generateContent: (rule) => {
|
|
2316
|
+
const lines = [];
|
|
2317
|
+
if (rule.frontmatter.description) {
|
|
2318
|
+
lines.push(`# ${rule.frontmatter.description}
|
|
2319
|
+
`);
|
|
2320
|
+
}
|
|
2321
|
+
lines.push(rule.content.trim());
|
|
2322
|
+
return lines.join("\n");
|
|
2323
|
+
}
|
|
2324
|
+
// NOTE: Claude Code specific logic is handled in the actual generator file
|
|
2325
|
+
// due to complex settings.json manipulation requirements
|
|
2326
|
+
},
|
|
2327
|
+
geminicli: {
|
|
2328
|
+
type: "complex",
|
|
2329
|
+
tool: "geminicli",
|
|
2330
|
+
fileExtension: ".md",
|
|
2331
|
+
ignoreFileName: ".aiexclude",
|
|
2332
|
+
generateContent: (rule) => {
|
|
2333
|
+
const lines = [];
|
|
2334
|
+
if (rule.frontmatter.description) {
|
|
2335
|
+
lines.push(`# ${rule.frontmatter.description}
|
|
2336
|
+
`);
|
|
2337
|
+
}
|
|
2338
|
+
lines.push(rule.content.trim());
|
|
2339
|
+
return lines.join("\n");
|
|
2340
|
+
}
|
|
2341
|
+
// Complex generation handled by existing generator
|
|
2342
|
+
},
|
|
2343
|
+
junie: {
|
|
2344
|
+
type: "complex",
|
|
2345
|
+
tool: "junie",
|
|
2346
|
+
fileExtension: ".md",
|
|
2347
|
+
ignoreFileName: ".aiignore",
|
|
2348
|
+
generateContent: (rule) => {
|
|
2349
|
+
const lines = [];
|
|
2350
|
+
if (rule.frontmatter.description) {
|
|
2351
|
+
lines.push(`# ${rule.frontmatter.description}
|
|
2352
|
+
`);
|
|
2353
|
+
}
|
|
2354
|
+
lines.push(rule.content.trim());
|
|
2355
|
+
return lines.join("\n");
|
|
2356
|
+
}
|
|
2357
|
+
// Complex generation handled by existing generator
|
|
2358
|
+
}
|
|
2359
|
+
};
|
|
2360
|
+
async function generateFromRegistry(tool, rules, config, baseDir) {
|
|
2361
|
+
const generatorConfig = GENERATOR_REGISTRY[tool];
|
|
2362
|
+
if (!generatorConfig) {
|
|
2363
|
+
throw new Error(`No generator configuration found for tool: ${tool}`);
|
|
2364
|
+
}
|
|
2365
|
+
if (generatorConfig.type === "simple") {
|
|
2366
|
+
const ruleConfig = {
|
|
2367
|
+
tool: generatorConfig.tool,
|
|
2368
|
+
fileExtension: generatorConfig.fileExtension,
|
|
2369
|
+
ignoreFileName: generatorConfig.ignoreFileName,
|
|
2370
|
+
generateContent: generatorConfig.generateContent,
|
|
2371
|
+
...generatorConfig.pathResolver && { pathResolver: generatorConfig.pathResolver }
|
|
2372
|
+
};
|
|
2373
|
+
return generateRulesConfig(rules, config, ruleConfig, baseDir);
|
|
2374
|
+
} else {
|
|
2375
|
+
const enhancedConfig = {
|
|
2376
|
+
tool: generatorConfig.tool,
|
|
2377
|
+
fileExtension: generatorConfig.fileExtension,
|
|
2378
|
+
ignoreFileName: generatorConfig.ignoreFileName,
|
|
2379
|
+
generateContent: generatorConfig.generateContent,
|
|
2380
|
+
...generatorConfig.generateRootContent && {
|
|
2381
|
+
generateRootContent: generatorConfig.generateRootContent
|
|
2382
|
+
},
|
|
2383
|
+
...generatorConfig.rootFilePath && { rootFilePath: generatorConfig.rootFilePath },
|
|
2384
|
+
...generatorConfig.generateDetailContent && {
|
|
2385
|
+
generateDetailContent: generatorConfig.generateDetailContent
|
|
2386
|
+
},
|
|
2387
|
+
...generatorConfig.detailSubDir && { detailSubDir: generatorConfig.detailSubDir },
|
|
2388
|
+
...generatorConfig.updateAdditionalConfig && {
|
|
2389
|
+
updateAdditionalConfig: generatorConfig.updateAdditionalConfig
|
|
2390
|
+
}
|
|
2391
|
+
};
|
|
2392
|
+
return generateComplexRules(rules, config, enhancedConfig, baseDir);
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2004
2396
|
// src/generators/rules/cline.ts
|
|
2005
2397
|
async function generateClineConfig(rules, config, baseDir) {
|
|
2006
|
-
return
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2398
|
+
return generateFromRegistry("cline", rules, config, baseDir);
|
|
2399
|
+
}
|
|
2400
|
+
|
|
2401
|
+
// src/generators/rules/codexcli.ts
|
|
2402
|
+
async function generateCodexConfig(rules, config, baseDir) {
|
|
2403
|
+
const outputs = [];
|
|
2404
|
+
if (rules.length === 0) {
|
|
2405
|
+
return outputs;
|
|
2406
|
+
}
|
|
2407
|
+
const sortedRules = [...rules].sort((a, b) => {
|
|
2408
|
+
if (a.frontmatter.root === true && b.frontmatter.root !== true) return -1;
|
|
2409
|
+
if (a.frontmatter.root !== true && b.frontmatter.root === true) return 1;
|
|
2410
|
+
return 0;
|
|
2411
|
+
});
|
|
2412
|
+
const concatenatedContent = generateConcatenatedCodexContent(sortedRules);
|
|
2413
|
+
if (concatenatedContent.trim()) {
|
|
2414
|
+
const outputDir = resolveOutputDir(config, "codexcli", baseDir);
|
|
2415
|
+
const filepath = `${outputDir}/codex.md`;
|
|
2416
|
+
outputs.push({
|
|
2417
|
+
tool: "codexcli",
|
|
2418
|
+
filepath,
|
|
2419
|
+
content: concatenatedContent
|
|
2420
|
+
});
|
|
2421
|
+
}
|
|
2422
|
+
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
2423
|
+
if (ignorePatterns.patterns.length > 0) {
|
|
2424
|
+
const ignorePath = resolvePath(".codexignore", baseDir);
|
|
2425
|
+
const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, "codexcli");
|
|
2426
|
+
outputs.push({
|
|
2427
|
+
tool: "codexcli",
|
|
2428
|
+
filepath: ignorePath,
|
|
2429
|
+
content: ignoreContent
|
|
2430
|
+
});
|
|
2431
|
+
}
|
|
2432
|
+
return outputs;
|
|
2433
|
+
}
|
|
2434
|
+
function generateConcatenatedCodexContent(rules) {
|
|
2435
|
+
const sections = [];
|
|
2436
|
+
for (const rule of rules) {
|
|
2437
|
+
const content = rule.content.trim();
|
|
2438
|
+
if (!content) {
|
|
2439
|
+
continue;
|
|
2440
|
+
}
|
|
2441
|
+
sections.push(content);
|
|
2442
|
+
}
|
|
2443
|
+
return sections.join("\n\n---\n\n");
|
|
2017
2444
|
}
|
|
2018
2445
|
|
|
2019
2446
|
// src/generators/rules/copilot.ts
|
|
2020
|
-
var
|
|
2447
|
+
var import_node_path9 = require("path");
|
|
2021
2448
|
async function generateCopilotConfig(rules, config, baseDir) {
|
|
2022
2449
|
return generateComplexRulesConfig(
|
|
2023
2450
|
rules,
|
|
@@ -2029,7 +2456,7 @@ async function generateCopilotConfig(rules, config, baseDir) {
|
|
|
2029
2456
|
generateContent: generateCopilotMarkdown,
|
|
2030
2457
|
getOutputPath: (rule, outputDir) => {
|
|
2031
2458
|
const baseFilename = rule.filename.replace(/\.md$/, "");
|
|
2032
|
-
return (0,
|
|
2459
|
+
return (0, import_node_path9.join)(outputDir, `${baseFilename}.instructions.md`);
|
|
2033
2460
|
}
|
|
2034
2461
|
},
|
|
2035
2462
|
baseDir
|
|
@@ -2050,7 +2477,7 @@ function generateCopilotMarkdown(rule) {
|
|
|
2050
2477
|
}
|
|
2051
2478
|
|
|
2052
2479
|
// src/generators/rules/cursor.ts
|
|
2053
|
-
var
|
|
2480
|
+
var import_node_path10 = require("path");
|
|
2054
2481
|
async function generateCursorConfig(rules, config, baseDir) {
|
|
2055
2482
|
return generateComplexRulesConfig(
|
|
2056
2483
|
rules,
|
|
@@ -2061,7 +2488,7 @@ async function generateCursorConfig(rules, config, baseDir) {
|
|
|
2061
2488
|
ignoreFileName: ".cursorignore",
|
|
2062
2489
|
generateContent: generateCursorMarkdown,
|
|
2063
2490
|
getOutputPath: (rule, outputDir) => {
|
|
2064
|
-
return (0,
|
|
2491
|
+
return (0, import_node_path10.join)(outputDir, `${rule.filename}.mdc`);
|
|
2065
2492
|
}
|
|
2066
2493
|
},
|
|
2067
2494
|
baseDir
|
|
@@ -2190,38 +2617,13 @@ function generateGuidelinesMarkdown(rootRule, detailRules) {
|
|
|
2190
2617
|
}
|
|
2191
2618
|
|
|
2192
2619
|
// src/generators/rules/kiro.ts
|
|
2193
|
-
var import_node_path10 = require("path");
|
|
2194
2620
|
async function generateKiroConfig(rules, config, baseDir) {
|
|
2195
|
-
|
|
2196
|
-
for (const rule of rules) {
|
|
2197
|
-
const content = generateKiroMarkdown(rule);
|
|
2198
|
-
const outputDir = baseDir ? (0, import_node_path10.join)(baseDir, config.outputPaths.kiro) : config.outputPaths.kiro;
|
|
2199
|
-
const filepath = (0, import_node_path10.join)(outputDir, `${rule.filename}.md`);
|
|
2200
|
-
outputs.push({
|
|
2201
|
-
tool: "kiro",
|
|
2202
|
-
filepath,
|
|
2203
|
-
content
|
|
2204
|
-
});
|
|
2205
|
-
}
|
|
2206
|
-
return outputs;
|
|
2207
|
-
}
|
|
2208
|
-
function generateKiroMarkdown(rule) {
|
|
2209
|
-
return rule.content.trim();
|
|
2621
|
+
return generateFromRegistry("kiro", rules, config, baseDir);
|
|
2210
2622
|
}
|
|
2211
2623
|
|
|
2212
2624
|
// src/generators/rules/roo.ts
|
|
2213
2625
|
async function generateRooConfig(rules, config, baseDir) {
|
|
2214
|
-
return
|
|
2215
|
-
rules,
|
|
2216
|
-
config,
|
|
2217
|
-
{
|
|
2218
|
-
tool: "roo",
|
|
2219
|
-
fileExtension: ".md",
|
|
2220
|
-
ignoreFileName: ".rooignore",
|
|
2221
|
-
generateContent: (rule) => rule.content.trim()
|
|
2222
|
-
},
|
|
2223
|
-
baseDir
|
|
2224
|
-
);
|
|
2626
|
+
return generateFromRegistry("roo", rules, config, baseDir);
|
|
2225
2627
|
}
|
|
2226
2628
|
|
|
2227
2629
|
// src/core/generator.ts
|
|
@@ -2280,6 +2682,8 @@ async function generateForTool(tool, rules, config, baseDir) {
|
|
|
2280
2682
|
return generateClineConfig(rules, config, baseDir);
|
|
2281
2683
|
case "claudecode":
|
|
2282
2684
|
return await generateClaudecodeConfig(rules, config, baseDir);
|
|
2685
|
+
case "codexcli":
|
|
2686
|
+
return generateCodexConfig(rules, config, baseDir);
|
|
2283
2687
|
case "roo":
|
|
2284
2688
|
return generateRooConfig(rules, config, baseDir);
|
|
2285
2689
|
case "geminicli":
|
|
@@ -2410,6 +2814,7 @@ var path4 = __toESM(require("path"), 1);
|
|
|
2410
2814
|
init_augmentcode();
|
|
2411
2815
|
init_claudecode();
|
|
2412
2816
|
init_cline();
|
|
2817
|
+
init_codexcli();
|
|
2413
2818
|
init_copilot();
|
|
2414
2819
|
init_cursor();
|
|
2415
2820
|
init_geminicli();
|
|
@@ -2483,6 +2888,11 @@ async function generateMcpConfigs(projectRoot, baseDir, targetTools) {
|
|
|
2483
2888
|
path: path4.join(targetRoot, ".cline", "mcp.json"),
|
|
2484
2889
|
generate: () => generateClineMcp(config)
|
|
2485
2890
|
},
|
|
2891
|
+
{
|
|
2892
|
+
tool: "codexcli-project",
|
|
2893
|
+
path: path4.join(targetRoot, ".codex", "mcp-config.json"),
|
|
2894
|
+
generate: () => generateCodexMcp(config)
|
|
2895
|
+
},
|
|
2486
2896
|
{
|
|
2487
2897
|
tool: "gemini-project",
|
|
2488
2898
|
path: path4.join(targetRoot, ".gemini", "settings.json"),
|
|
@@ -2518,7 +2928,7 @@ async function generateMcpConfigs(projectRoot, baseDir, targetTools) {
|
|
|
2518
2928
|
try {
|
|
2519
2929
|
const content = generator.generate();
|
|
2520
2930
|
const parsed = JSON.parse(content);
|
|
2521
|
-
if (generator.tool.includes("augmentcode") || generator.tool.includes("claude") || generator.tool.includes("cline") || generator.tool.includes("cursor") || generator.tool.includes("gemini") || generator.tool.includes("junie") || generator.tool.includes("kiro") || generator.tool.includes("roo")) {
|
|
2931
|
+
if (generator.tool.includes("augmentcode") || generator.tool.includes("claude") || generator.tool.includes("cline") || generator.tool.includes("codexcli") || generator.tool.includes("cursor") || generator.tool.includes("gemini") || generator.tool.includes("junie") || generator.tool.includes("kiro") || generator.tool.includes("roo")) {
|
|
2522
2932
|
if (!parsed.mcpServers || Object.keys(parsed.mcpServers).length === 0) {
|
|
2523
2933
|
results.push({
|
|
2524
2934
|
tool: generator.tool,
|
|
@@ -2743,6 +3153,8 @@ var gitignoreCommand = async () => {
|
|
|
2743
3153
|
"**/.clineignore",
|
|
2744
3154
|
"**/CLAUDE.md",
|
|
2745
3155
|
"**/.claude/memories/",
|
|
3156
|
+
"**/codex.md",
|
|
3157
|
+
"**/.codexignore",
|
|
2746
3158
|
"**/.roo/rules/",
|
|
2747
3159
|
"**/.rooignore",
|
|
2748
3160
|
"**/.copilotignore",
|
|
@@ -2761,6 +3173,7 @@ var gitignoreCommand = async () => {
|
|
|
2761
3173
|
"**/.cursor/mcp.json",
|
|
2762
3174
|
"**/.cline/mcp.json",
|
|
2763
3175
|
"**/.vscode/mcp.json",
|
|
3176
|
+
"**/.codex/mcp-config.json",
|
|
2764
3177
|
"**/.gemini/settings.json",
|
|
2765
3178
|
"**/.roo/mcp.json"
|
|
2766
3179
|
];
|
|
@@ -2819,36 +3232,63 @@ function addRules(result, rules) {
|
|
|
2819
3232
|
}
|
|
2820
3233
|
result.rules.push(...rules);
|
|
2821
3234
|
}
|
|
2822
|
-
function handleParseError(error, context) {
|
|
2823
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2824
|
-
return `${context}: ${errorMessage}`;
|
|
2825
|
-
}
|
|
2826
3235
|
async function safeReadFile(operation, errorContext) {
|
|
2827
3236
|
try {
|
|
2828
3237
|
const result = await operation();
|
|
2829
|
-
return
|
|
3238
|
+
return createSuccessResult(result);
|
|
2830
3239
|
} catch (error) {
|
|
2831
|
-
return
|
|
2832
|
-
success: false,
|
|
2833
|
-
error: handleParseError(error, errorContext)
|
|
2834
|
-
};
|
|
3240
|
+
return createErrorResult(error, errorContext);
|
|
2835
3241
|
}
|
|
2836
3242
|
}
|
|
2837
3243
|
|
|
2838
3244
|
// src/parsers/augmentcode.ts
|
|
2839
3245
|
async function parseAugmentcodeConfiguration(baseDir = process.cwd()) {
|
|
3246
|
+
return parseUnifiedAugmentcode(baseDir, {
|
|
3247
|
+
rulesDir: ".augment/rules",
|
|
3248
|
+
targetName: "augmentcode",
|
|
3249
|
+
filenamePrefix: "augmentcode"
|
|
3250
|
+
});
|
|
3251
|
+
}
|
|
3252
|
+
async function parseAugmentcodeLegacyConfiguration(baseDir = process.cwd()) {
|
|
3253
|
+
return parseUnifiedAugmentcode(baseDir, {
|
|
3254
|
+
legacyFilePath: ".augment-guidelines",
|
|
3255
|
+
targetName: "augmentcode-legacy",
|
|
3256
|
+
filenamePrefix: "augmentcode-legacy"
|
|
3257
|
+
});
|
|
3258
|
+
}
|
|
3259
|
+
async function parseUnifiedAugmentcode(baseDir, config) {
|
|
2840
3260
|
const result = createParseResult();
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
3261
|
+
if (config.rulesDir) {
|
|
3262
|
+
const rulesDir = (0, import_node_path14.join)(baseDir, config.rulesDir);
|
|
3263
|
+
if (await fileExists(rulesDir)) {
|
|
3264
|
+
const rulesResult = await parseAugmentRules(rulesDir, config);
|
|
3265
|
+
addRules(result, rulesResult.rules);
|
|
3266
|
+
result.errors.push(...rulesResult.errors);
|
|
3267
|
+
} else {
|
|
3268
|
+
addError(
|
|
3269
|
+
result,
|
|
3270
|
+
`No AugmentCode configuration found. Expected ${config.rulesDir} directory.`
|
|
3271
|
+
);
|
|
3272
|
+
}
|
|
3273
|
+
}
|
|
3274
|
+
if (config.legacyFilePath) {
|
|
3275
|
+
const legacyPath = (0, import_node_path14.join)(baseDir, config.legacyFilePath);
|
|
3276
|
+
if (await fileExists(legacyPath)) {
|
|
3277
|
+
const legacyResult = await parseAugmentGuidelines(legacyPath, config);
|
|
3278
|
+
if (legacyResult.rule) {
|
|
3279
|
+
addRule(result, legacyResult.rule);
|
|
3280
|
+
}
|
|
3281
|
+
result.errors.push(...legacyResult.errors);
|
|
3282
|
+
} else {
|
|
3283
|
+
addError(
|
|
3284
|
+
result,
|
|
3285
|
+
`No AugmentCode legacy configuration found. Expected ${config.legacyFilePath} file.`
|
|
3286
|
+
);
|
|
3287
|
+
}
|
|
2848
3288
|
}
|
|
2849
3289
|
return { rules: result.rules || [], errors: result.errors };
|
|
2850
3290
|
}
|
|
2851
|
-
async function parseAugmentRules(rulesDir) {
|
|
3291
|
+
async function parseAugmentRules(rulesDir, config) {
|
|
2852
3292
|
const rules = [];
|
|
2853
3293
|
const errors = [];
|
|
2854
3294
|
try {
|
|
@@ -2868,7 +3308,7 @@ async function parseAugmentRules(rulesDir) {
|
|
|
2868
3308
|
const filename = (0, import_node_path14.basename)(file, file.endsWith(".mdc") ? ".mdc" : ".md");
|
|
2869
3309
|
const frontmatter = {
|
|
2870
3310
|
root: isRoot,
|
|
2871
|
-
targets: [
|
|
3311
|
+
targets: [config.targetName],
|
|
2872
3312
|
description,
|
|
2873
3313
|
globs: ["**/*"],
|
|
2874
3314
|
// AugmentCode doesn't use specific globs in the same way
|
|
@@ -2877,7 +3317,7 @@ async function parseAugmentRules(rulesDir) {
|
|
|
2877
3317
|
rules.push({
|
|
2878
3318
|
frontmatter,
|
|
2879
3319
|
content: parsed.content.trim(),
|
|
2880
|
-
filename:
|
|
3320
|
+
filename: `${config.filenamePrefix}-${ruleType}-${filename}`,
|
|
2881
3321
|
filepath: filePath
|
|
2882
3322
|
});
|
|
2883
3323
|
} catch (error) {
|
|
@@ -2888,50 +3328,33 @@ async function parseAugmentRules(rulesDir) {
|
|
|
2888
3328
|
}
|
|
2889
3329
|
} catch (error) {
|
|
2890
3330
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2891
|
-
errors.push(`Failed to read .
|
|
3331
|
+
errors.push(`Failed to read ${config.rulesDir || rulesDir} directory: ${errorMessage}`);
|
|
2892
3332
|
}
|
|
2893
3333
|
return { rules, errors };
|
|
2894
3334
|
}
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
if (content.trim()) {
|
|
2919
|
-
const frontmatter = {
|
|
2920
|
-
root: true,
|
|
2921
|
-
// Legacy guidelines become root rules
|
|
2922
|
-
targets: ["augmentcode-legacy"],
|
|
2923
|
-
description: "Legacy AugmentCode guidelines",
|
|
2924
|
-
globs: ["**/*"]
|
|
2925
|
-
};
|
|
2926
|
-
return {
|
|
2927
|
-
frontmatter,
|
|
2928
|
-
content: content.trim(),
|
|
2929
|
-
filename: "augmentcode-legacy-guidelines",
|
|
2930
|
-
filepath: guidelinesPath
|
|
2931
|
-
};
|
|
2932
|
-
}
|
|
2933
|
-
return null;
|
|
2934
|
-
}, "Failed to parse .augment-guidelines");
|
|
3335
|
+
async function parseAugmentGuidelines(guidelinesPath, config) {
|
|
3336
|
+
const parseResult = await safeReadFile(
|
|
3337
|
+
async () => {
|
|
3338
|
+
const content = await readFileContent(guidelinesPath);
|
|
3339
|
+
if (content.trim()) {
|
|
3340
|
+
const frontmatter = {
|
|
3341
|
+
root: true,
|
|
3342
|
+
// Legacy guidelines become root rules
|
|
3343
|
+
targets: [config.targetName],
|
|
3344
|
+
description: "Legacy AugmentCode guidelines",
|
|
3345
|
+
globs: ["**/*"]
|
|
3346
|
+
};
|
|
3347
|
+
return {
|
|
3348
|
+
frontmatter,
|
|
3349
|
+
content: content.trim(),
|
|
3350
|
+
filename: `${config.filenamePrefix}-guidelines`,
|
|
3351
|
+
filepath: guidelinesPath
|
|
3352
|
+
};
|
|
3353
|
+
}
|
|
3354
|
+
return null;
|
|
3355
|
+
},
|
|
3356
|
+
`Failed to parse ${config.legacyFilePath || guidelinesPath}`
|
|
3357
|
+
);
|
|
2935
3358
|
if (parseResult.success) {
|
|
2936
3359
|
return { rule: parseResult.result || null, errors: [] };
|
|
2937
3360
|
} else {
|
|
@@ -2940,33 +3363,36 @@ async function parseAugmentGuidelines(guidelinesPath) {
|
|
|
2940
3363
|
}
|
|
2941
3364
|
|
|
2942
3365
|
// src/parsers/shared-helpers.ts
|
|
2943
|
-
var
|
|
3366
|
+
var import_node_path15 = require("path");
|
|
2944
3367
|
var import_gray_matter3 = __toESM(require("gray-matter"), 1);
|
|
2945
3368
|
async function parseConfigurationFiles(baseDir = process.cwd(), config) {
|
|
2946
3369
|
const errors = [];
|
|
2947
3370
|
const rules = [];
|
|
2948
3371
|
if (config.mainFile) {
|
|
2949
|
-
const
|
|
3372
|
+
const mainFile = config.mainFile;
|
|
3373
|
+
const mainFilePath = resolvePath(mainFile.path, baseDir);
|
|
2950
3374
|
if (await fileExists(mainFilePath)) {
|
|
2951
|
-
|
|
3375
|
+
const result = await safeAsyncOperation(async () => {
|
|
2952
3376
|
const rawContent = await readFileContent(mainFilePath);
|
|
2953
3377
|
let content;
|
|
2954
3378
|
let frontmatter;
|
|
2955
|
-
if (
|
|
3379
|
+
if (mainFile.useFrontmatter) {
|
|
2956
3380
|
const parsed = (0, import_gray_matter3.default)(rawContent);
|
|
2957
3381
|
content = parsed.content.trim();
|
|
3382
|
+
const parsedFrontmatter = parsed.data;
|
|
2958
3383
|
frontmatter = {
|
|
2959
|
-
root: false,
|
|
3384
|
+
root: mainFile.isRoot ?? false,
|
|
2960
3385
|
targets: [config.tool],
|
|
2961
|
-
description:
|
|
2962
|
-
globs: ["**/*"]
|
|
3386
|
+
description: parsedFrontmatter.description || mainFile.description,
|
|
3387
|
+
globs: Array.isArray(parsedFrontmatter.globs) ? parsedFrontmatter.globs : ["**/*"],
|
|
3388
|
+
...parsedFrontmatter.tags && { tags: parsedFrontmatter.tags }
|
|
2963
3389
|
};
|
|
2964
3390
|
} else {
|
|
2965
3391
|
content = rawContent.trim();
|
|
2966
3392
|
frontmatter = {
|
|
2967
|
-
root: false,
|
|
3393
|
+
root: mainFile.isRoot ?? false,
|
|
2968
3394
|
targets: [config.tool],
|
|
2969
|
-
description:
|
|
3395
|
+
description: mainFile.description,
|
|
2970
3396
|
globs: ["**/*"]
|
|
2971
3397
|
};
|
|
2972
3398
|
}
|
|
@@ -2974,43 +3400,52 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
|
|
|
2974
3400
|
rules.push({
|
|
2975
3401
|
frontmatter,
|
|
2976
3402
|
content,
|
|
2977
|
-
filename: "instructions",
|
|
3403
|
+
filename: mainFile.filenameOverride || "instructions",
|
|
2978
3404
|
filepath: mainFilePath
|
|
2979
3405
|
});
|
|
2980
3406
|
}
|
|
2981
|
-
}
|
|
2982
|
-
|
|
2983
|
-
errors.push(
|
|
3407
|
+
}, `Failed to parse ${mainFile.path}`);
|
|
3408
|
+
if (!result.success) {
|
|
3409
|
+
errors.push(result.error);
|
|
2984
3410
|
}
|
|
2985
3411
|
}
|
|
2986
3412
|
}
|
|
2987
3413
|
if (config.directories) {
|
|
2988
3414
|
for (const dirConfig of config.directories) {
|
|
2989
|
-
const dirPath = (
|
|
3415
|
+
const dirPath = resolvePath(dirConfig.directory, baseDir);
|
|
2990
3416
|
if (await fileExists(dirPath)) {
|
|
2991
|
-
|
|
3417
|
+
const result = await safeAsyncOperation(async () => {
|
|
2992
3418
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
2993
3419
|
const files = await readdir2(dirPath);
|
|
2994
3420
|
for (const file of files) {
|
|
2995
3421
|
if (file.endsWith(dirConfig.filePattern)) {
|
|
2996
|
-
const filePath = (0,
|
|
2997
|
-
|
|
3422
|
+
const filePath = (0, import_node_path15.join)(dirPath, file);
|
|
3423
|
+
const fileResult = await safeAsyncOperation(async () => {
|
|
2998
3424
|
const rawContent = await readFileContent(filePath);
|
|
2999
3425
|
let content;
|
|
3426
|
+
let frontmatter;
|
|
3427
|
+
const filename = file.replace(new RegExp(`\\${dirConfig.filePattern}$`), "");
|
|
3000
3428
|
if (dirConfig.filePattern === ".instructions.md") {
|
|
3001
3429
|
const parsed = (0, import_gray_matter3.default)(rawContent);
|
|
3002
3430
|
content = parsed.content.trim();
|
|
3431
|
+
const parsedFrontmatter = parsed.data;
|
|
3432
|
+
frontmatter = {
|
|
3433
|
+
root: false,
|
|
3434
|
+
targets: [config.tool],
|
|
3435
|
+
description: parsedFrontmatter.description || `${dirConfig.description}: ${filename}`,
|
|
3436
|
+
globs: Array.isArray(parsedFrontmatter.globs) ? parsedFrontmatter.globs : ["**/*"],
|
|
3437
|
+
...parsedFrontmatter.tags && { tags: parsedFrontmatter.tags }
|
|
3438
|
+
};
|
|
3003
3439
|
} else {
|
|
3004
3440
|
content = rawContent.trim();
|
|
3005
|
-
|
|
3006
|
-
if (content) {
|
|
3007
|
-
const filename = file.replace(new RegExp(`\\${dirConfig.filePattern}$`), "");
|
|
3008
|
-
const frontmatter = {
|
|
3441
|
+
frontmatter = {
|
|
3009
3442
|
root: false,
|
|
3010
3443
|
targets: [config.tool],
|
|
3011
3444
|
description: `${dirConfig.description}: ${filename}`,
|
|
3012
3445
|
globs: ["**/*"]
|
|
3013
3446
|
};
|
|
3447
|
+
}
|
|
3448
|
+
if (content) {
|
|
3014
3449
|
rules.push({
|
|
3015
3450
|
frontmatter,
|
|
3016
3451
|
content,
|
|
@@ -3018,15 +3453,15 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
|
|
|
3018
3453
|
filepath: filePath
|
|
3019
3454
|
});
|
|
3020
3455
|
}
|
|
3021
|
-
}
|
|
3022
|
-
|
|
3023
|
-
errors.push(
|
|
3456
|
+
}, `Failed to parse ${filePath}`);
|
|
3457
|
+
if (!fileResult.success) {
|
|
3458
|
+
errors.push(fileResult.error);
|
|
3024
3459
|
}
|
|
3025
3460
|
}
|
|
3026
3461
|
}
|
|
3027
|
-
}
|
|
3028
|
-
|
|
3029
|
-
errors.push(
|
|
3462
|
+
}, `Failed to parse ${dirConfig.directory} files`);
|
|
3463
|
+
if (!result.success) {
|
|
3464
|
+
errors.push(result.error);
|
|
3030
3465
|
}
|
|
3031
3466
|
}
|
|
3032
3467
|
}
|
|
@@ -3041,7 +3476,7 @@ async function parseMemoryBasedConfiguration(baseDir = process.cwd(), config) {
|
|
|
3041
3476
|
const rules = [];
|
|
3042
3477
|
let ignorePatterns;
|
|
3043
3478
|
let mcpServers;
|
|
3044
|
-
const mainFilePath = (
|
|
3479
|
+
const mainFilePath = resolvePath(config.mainFileName, baseDir);
|
|
3045
3480
|
if (!await fileExists(mainFilePath)) {
|
|
3046
3481
|
errors.push(`${config.mainFileName} file not found`);
|
|
3047
3482
|
return { rules, errors };
|
|
@@ -3052,12 +3487,12 @@ async function parseMemoryBasedConfiguration(baseDir = process.cwd(), config) {
|
|
|
3052
3487
|
if (mainRule) {
|
|
3053
3488
|
rules.push(mainRule);
|
|
3054
3489
|
}
|
|
3055
|
-
const memoryDir = (
|
|
3490
|
+
const memoryDir = resolvePath(config.memoryDirPath, baseDir);
|
|
3056
3491
|
if (await fileExists(memoryDir)) {
|
|
3057
3492
|
const memoryRules = await parseMemoryFiles(memoryDir, config);
|
|
3058
3493
|
rules.push(...memoryRules);
|
|
3059
3494
|
}
|
|
3060
|
-
const settingsPath = (
|
|
3495
|
+
const settingsPath = resolvePath(config.settingsPath, baseDir);
|
|
3061
3496
|
if (await fileExists(settingsPath)) {
|
|
3062
3497
|
const settingsResult = await parseSettingsFile(settingsPath, config.tool);
|
|
3063
3498
|
if (settingsResult.ignorePatterns) {
|
|
@@ -3069,7 +3504,7 @@ async function parseMemoryBasedConfiguration(baseDir = process.cwd(), config) {
|
|
|
3069
3504
|
errors.push(...settingsResult.errors);
|
|
3070
3505
|
}
|
|
3071
3506
|
if (config.additionalIgnoreFile) {
|
|
3072
|
-
const additionalIgnorePath = (
|
|
3507
|
+
const additionalIgnorePath = resolvePath(config.additionalIgnoreFile.path, baseDir);
|
|
3073
3508
|
if (await fileExists(additionalIgnorePath)) {
|
|
3074
3509
|
const additionalPatterns = await config.additionalIgnoreFile.parser(additionalIgnorePath);
|
|
3075
3510
|
if (additionalPatterns.length > 0) {
|
|
@@ -3078,8 +3513,7 @@ async function parseMemoryBasedConfiguration(baseDir = process.cwd(), config) {
|
|
|
3078
3513
|
}
|
|
3079
3514
|
}
|
|
3080
3515
|
} catch (error) {
|
|
3081
|
-
|
|
3082
|
-
errors.push(`Failed to parse ${config.tool} configuration: ${errorMessage}`);
|
|
3516
|
+
errors.push(`Failed to parse ${config.tool} configuration: ${getErrorMessage(error)}`);
|
|
3083
3517
|
}
|
|
3084
3518
|
return {
|
|
3085
3519
|
rules,
|
|
@@ -3123,10 +3557,10 @@ async function parseMemoryFiles(memoryDir, config) {
|
|
|
3123
3557
|
const files = await readdir2(memoryDir);
|
|
3124
3558
|
for (const file of files) {
|
|
3125
3559
|
if (file.endsWith(".md")) {
|
|
3126
|
-
const filePath = (0,
|
|
3560
|
+
const filePath = (0, import_node_path15.join)(memoryDir, file);
|
|
3127
3561
|
const content = await readFileContent(filePath);
|
|
3128
3562
|
if (content.trim()) {
|
|
3129
|
-
const filename = (0,
|
|
3563
|
+
const filename = (0, import_node_path15.basename)(file, ".md");
|
|
3130
3564
|
const frontmatter = {
|
|
3131
3565
|
root: false,
|
|
3132
3566
|
targets: [config.tool],
|
|
@@ -3175,8 +3609,7 @@ async function parseSettingsFile(settingsPath, tool) {
|
|
|
3175
3609
|
mcpServers = parseResult.data.mcpServers;
|
|
3176
3610
|
}
|
|
3177
3611
|
} catch (error) {
|
|
3178
|
-
|
|
3179
|
-
errors.push(`Failed to parse settings.json: ${errorMessage}`);
|
|
3612
|
+
errors.push(`Failed to parse settings.json: ${getErrorMessage(error)}`);
|
|
3180
3613
|
}
|
|
3181
3614
|
return {
|
|
3182
3615
|
errors,
|
|
@@ -3218,6 +3651,9 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
|
|
|
3218
3651
|
});
|
|
3219
3652
|
}
|
|
3220
3653
|
|
|
3654
|
+
// src/parsers/codexcli.ts
|
|
3655
|
+
var import_node_path16 = require("path");
|
|
3656
|
+
|
|
3221
3657
|
// src/parsers/copilot.ts
|
|
3222
3658
|
async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
3223
3659
|
return parseConfigurationFiles(baseDir, {
|
|
@@ -3953,12 +4389,12 @@ async function watchCommand() {
|
|
|
3953
4389
|
|
|
3954
4390
|
// src/cli/index.ts
|
|
3955
4391
|
var program = new import_commander.Command();
|
|
3956
|
-
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.
|
|
4392
|
+
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.55.0");
|
|
3957
4393
|
program.command("init").description("Initialize rulesync in current directory").action(initCommand);
|
|
3958
4394
|
program.command("add <filename>").description("Add a new rule file").action(addCommand);
|
|
3959
4395
|
program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
|
|
3960
4396
|
program.command("import").description("Import configurations from AI tools to rulesync format").option("--augmentcode", "Import from AugmentCode (.augment/rules/)").option("--augmentcode-legacy", "Import from AugmentCode legacy format (.augment-guidelines)").option("--claudecode", "Import from Claude Code (CLAUDE.md)").option("--cursor", "Import from Cursor (.cursorrules)").option("--copilot", "Import from GitHub Copilot (.github/copilot-instructions.md)").option("--cline", "Import from Cline (.cline/instructions.md)").option("--roo", "Import from Roo Code (.roo/instructions.md)").option("--geminicli", "Import from Gemini CLI (GEMINI.md)").option("--junie", "Import from JetBrains Junie (.junie/guidelines.md)").option("-v, --verbose", "Verbose output").action(importCommand);
|
|
3961
|
-
program.command("generate").description("Generate configuration files for AI tools").option("--augmentcode", "Generate only for AugmentCode").option("--augmentcode-legacy", "Generate only for AugmentCode legacy format").option("--copilot", "Generate only for GitHub Copilot").option("--cursor", "Generate only for Cursor").option("--cline", "Generate only for Cline").option("--claudecode", "Generate only for Claude Code").option("--roo", "Generate only for Roo Code").option("--geminicli", "Generate only for Gemini CLI").option("--junie", "Generate only for JetBrains Junie").option("--kiro", "Generate only for Kiro IDE").option("--delete", "Delete all existing files in output directories before generating").option(
|
|
4397
|
+
program.command("generate").description("Generate configuration files for AI tools").option("--augmentcode", "Generate only for AugmentCode").option("--augmentcode-legacy", "Generate only for AugmentCode legacy format").option("--copilot", "Generate only for GitHub Copilot").option("--cursor", "Generate only for Cursor").option("--cline", "Generate only for Cline").option("--codexcli", "Generate only for OpenAI Codex CLI").option("--claudecode", "Generate only for Claude Code").option("--roo", "Generate only for Roo Code").option("--geminicli", "Generate only for Gemini CLI").option("--junie", "Generate only for JetBrains Junie").option("--kiro", "Generate only for Kiro IDE").option("--delete", "Delete all existing files in output directories before generating").option(
|
|
3962
4398
|
"-b, --base-dir <paths>",
|
|
3963
4399
|
"Base directories to generate files (comma-separated for multiple paths)"
|
|
3964
4400
|
).option("-v, --verbose", "Verbose output").option("-c, --config <path>", "Path to configuration file").option("--no-config", "Disable configuration file loading").action(async (options) => {
|
|
@@ -3968,6 +4404,7 @@ program.command("generate").description("Generate configuration files for AI too
|
|
|
3968
4404
|
if (options.copilot) tools.push("copilot");
|
|
3969
4405
|
if (options.cursor) tools.push("cursor");
|
|
3970
4406
|
if (options.cline) tools.push("cline");
|
|
4407
|
+
if (options.codexcli) tools.push("codexcli");
|
|
3971
4408
|
if (options.claudecode) tools.push("claudecode");
|
|
3972
4409
|
if (options.roo) tools.push("roo");
|
|
3973
4410
|
if (options.geminicli) tools.push("geminicli");
|