rulesync 0.53.0 → 0.54.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.
Files changed (27) hide show
  1. package/README.ja.md +186 -23
  2. package/README.md +101 -25
  3. package/dist/{augmentcode-ICLQ2NEZ.js → augmentcode-MJYD2Y4S.js} +2 -2
  4. package/dist/{chunk-TTHBLXOB.js → chunk-3PHMFVXP.js} +1 -1
  5. package/dist/{chunk-FFW6TGCM.js → chunk-BEPSWIZC.js} +1 -1
  6. package/dist/chunk-D7XQ4OHK.js +145 -0
  7. package/dist/{chunk-OPZOVKIL.js → chunk-ORNO5MOO.js} +1 -1
  8. package/dist/{chunk-Y2XH4E5R.js → chunk-OXKDEZJK.js} +1 -1
  9. package/dist/{chunk-FNL2KPM3.js → chunk-OY6BYYIX.js} +1 -1
  10. package/dist/{chunk-YPIFCGAP.js → chunk-PPAQWVXX.js} +1 -1
  11. package/dist/{chunk-QUJMXHNR.js → chunk-QVPD6ENS.js} +1 -1
  12. package/dist/{chunk-Y26DXTAT.js → chunk-TJKD6LEW.js} +1 -1
  13. package/dist/{chunk-HMMTSS5E.js → chunk-UHANRG2O.js} +1 -1
  14. package/dist/{chunk-IXCMY24P.js → chunk-UZCJNUXO.js} +1 -1
  15. package/dist/{chunk-USKQYIZ2.js → chunk-VI6SBYFB.js} +1 -0
  16. package/dist/{claudecode-4XWK2WAY.js → claudecode-CKGUHLRR.js} +3 -3
  17. package/dist/{cline-MNXOHP77.js → cline-Z5C656VR.js} +3 -3
  18. package/dist/codexcli-VFUJKSIJ.js +10 -0
  19. package/dist/{copilot-ARYIWVJ7.js → copilot-4WQS5TA7.js} +2 -2
  20. package/dist/{cursor-FCS74IAH.js → cursor-HOB2F2V2.js} +2 -2
  21. package/dist/{geminicli-VOPV6DXZ.js → geminicli-XTMQTIU2.js} +2 -2
  22. package/dist/index.cjs +267 -21
  23. package/dist/index.js +213 -33
  24. package/dist/{junie-A2Y2WZI4.js → junie-AN6CR7DD.js} +2 -2
  25. package/dist/{kiro-MHIK4UBV.js → kiro-PTUZOHQ2.js} +2 -2
  26. package/dist/{roo-VG4IUNTE.js → roo-WOMS36KU.js} +2 -2
  27. 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)
@@ -1672,6 +1743,135 @@ var ignoreConfigs = {
1672
1743
  }
1673
1744
  return augmentPatterns;
1674
1745
  }
1746
+ },
1747
+ codexcli: {
1748
+ tool: "codexcli",
1749
+ filename: ".codexignore",
1750
+ header: [
1751
+ "# Generated by rulesync - OpenAI Codex CLI ignore file",
1752
+ "# This file controls which files are excluded from Codex CLI's AI context",
1753
+ "# Note: .codexignore is a community-requested feature (GitHub Issue #205)",
1754
+ "# Currently using proposed syntax based on .gitignore patterns"
1755
+ ],
1756
+ corePatterns: [
1757
+ "# \u2500\u2500\u2500\u2500\u2500 Security & Credentials (Critical) \u2500\u2500\u2500\u2500\u2500",
1758
+ "# Environment files",
1759
+ ".env",
1760
+ ".env.*",
1761
+ "!.env.example",
1762
+ "",
1763
+ "# Private keys and certificates",
1764
+ "*.key",
1765
+ "*.pem",
1766
+ "*.p12",
1767
+ "*.pfx",
1768
+ "*.der",
1769
+ "*.crt",
1770
+ "",
1771
+ "# SSH keys",
1772
+ "id_rsa*",
1773
+ "id_dsa*",
1774
+ "*.ppk",
1775
+ "",
1776
+ "# API keys and secrets",
1777
+ "api-keys.json",
1778
+ "credentials.json",
1779
+ "secrets.json",
1780
+ "**/apikeys/",
1781
+ "**/*_token*",
1782
+ "**/*_secret*",
1783
+ "**/*api_key*",
1784
+ "",
1785
+ "# Cloud provider credentials",
1786
+ "aws-credentials.json",
1787
+ "gcp-service-account*.json",
1788
+ "azure-credentials.json",
1789
+ ".aws/",
1790
+ "",
1791
+ "# \u2500\u2500\u2500\u2500\u2500 Database & Infrastructure Secrets \u2500\u2500\u2500\u2500\u2500",
1792
+ "# Database configuration",
1793
+ "*.db",
1794
+ "*.sqlite",
1795
+ "*.sqlite3",
1796
+ "database.yml",
1797
+ "**/database/config.*",
1798
+ "",
1799
+ "# Infrastructure as Code secrets",
1800
+ "*.tfstate",
1801
+ "*.tfstate.*",
1802
+ "terraform.tfvars",
1803
+ "secrets.auto.tfvars",
1804
+ ".terraform/",
1805
+ "",
1806
+ "# Kubernetes secrets",
1807
+ "**/k8s/**/secret*.yaml",
1808
+ "**/kubernetes/**/secret*.yaml",
1809
+ "",
1810
+ "# \u2500\u2500\u2500\u2500\u2500 Business Sensitive Data \u2500\u2500\u2500\u2500\u2500",
1811
+ "# Sensitive directories",
1812
+ "secrets/",
1813
+ "private/",
1814
+ "confidential/",
1815
+ "internal-docs/",
1816
+ "company-secrets/",
1817
+ "",
1818
+ "# Customer and personal data",
1819
+ "customer-data/",
1820
+ "pii/",
1821
+ "personal-data/",
1822
+ "**/*customer*.csv",
1823
+ "**/*personal*.json",
1824
+ "",
1825
+ "# \u2500\u2500\u2500\u2500\u2500 Build Artifacts & Large Files \u2500\u2500\u2500\u2500\u2500",
1826
+ "# Build outputs (may contain embedded secrets)",
1827
+ "dist/",
1828
+ "build/",
1829
+ "out/",
1830
+ ".next/",
1831
+ ".nuxt/",
1832
+ "",
1833
+ "# Large files that slow down AI processing",
1834
+ "*.zip",
1835
+ "*.tar.gz",
1836
+ "*.rar",
1837
+ "**/*.{mp4,avi,mov,mkv}",
1838
+ "**/*.{pdf,doc,docx}",
1839
+ "",
1840
+ "# Data files",
1841
+ "*.csv",
1842
+ "*.tsv",
1843
+ "*.xlsx",
1844
+ "data/",
1845
+ "datasets/",
1846
+ "",
1847
+ "# \u2500\u2500\u2500\u2500\u2500 Development Environment \u2500\u2500\u2500\u2500\u2500",
1848
+ "# Personal IDE settings",
1849
+ ".vscode/settings.json",
1850
+ ".idea/workspace.xml",
1851
+ "",
1852
+ "# Temporary files",
1853
+ "*.swp",
1854
+ "*.swo",
1855
+ "*~",
1856
+ "*.tmp",
1857
+ "",
1858
+ "# Test data with sensitive content",
1859
+ "test-data/sensitive/",
1860
+ "tests/fixtures/real-data/**",
1861
+ "",
1862
+ "# \u2500\u2500\u2500\u2500\u2500 Logs & Runtime Data \u2500\u2500\u2500\u2500\u2500",
1863
+ "*.log",
1864
+ "logs/",
1865
+ ".cache/",
1866
+ "",
1867
+ "# \u2500\u2500\u2500\u2500\u2500 Re-include Important Files \u2500\u2500\u2500\u2500\u2500",
1868
+ "# Allow configuration examples and documentation",
1869
+ "!secrets/README.md",
1870
+ "!config/*.example.*",
1871
+ "!docs/**/*.md"
1872
+ ],
1873
+ includeCommonPatterns: false,
1874
+ projectPatternsHeader: "# \u2500\u2500\u2500\u2500\u2500 Project-specific patterns from rulesync rules \u2500\u2500\u2500\u2500\u2500"
1675
1875
  }
1676
1876
  };
1677
1877
 
@@ -2016,6 +2216,37 @@ async function generateClineConfig(rules, config, baseDir) {
2016
2216
  );
2017
2217
  }
2018
2218
 
2219
+ // src/generators/rules/codexcli.ts
2220
+ async function generateCodexConfig(rules, config, baseDir) {
2221
+ const generatorConfig = {
2222
+ tool: "codexcli",
2223
+ fileExtension: ".md",
2224
+ ignoreFileName: ".codexignore",
2225
+ generateContent: generateCodexInstructionsMarkdown,
2226
+ pathResolver: (rule, outputDir) => {
2227
+ if (rule.frontmatter.root === true) {
2228
+ return `${outputDir}/codex.md`;
2229
+ }
2230
+ return `${outputDir}/${rule.filename}.md`;
2231
+ }
2232
+ };
2233
+ return generateRulesConfig(rules, config, generatorConfig, baseDir);
2234
+ }
2235
+ function generateCodexInstructionsMarkdown(rule) {
2236
+ const lines = [];
2237
+ if (rule.frontmatter.root === false && rule.frontmatter.description && rule.frontmatter.description !== "Main instructions" && !rule.frontmatter.description.includes("Project-level Codex CLI instructions")) {
2238
+ lines.push(`<!-- ${rule.frontmatter.description} -->`);
2239
+ if (rule.content.trim()) {
2240
+ lines.push("");
2241
+ }
2242
+ }
2243
+ const content = rule.content.trim();
2244
+ if (content) {
2245
+ lines.push(content);
2246
+ }
2247
+ return lines.join("\n");
2248
+ }
2249
+
2019
2250
  // src/generators/rules/copilot.ts
2020
2251
  var import_node_path8 = require("path");
2021
2252
  async function generateCopilotConfig(rules, config, baseDir) {
@@ -2280,6 +2511,8 @@ async function generateForTool(tool, rules, config, baseDir) {
2280
2511
  return generateClineConfig(rules, config, baseDir);
2281
2512
  case "claudecode":
2282
2513
  return await generateClaudecodeConfig(rules, config, baseDir);
2514
+ case "codexcli":
2515
+ return generateCodexConfig(rules, config, baseDir);
2283
2516
  case "roo":
2284
2517
  return generateRooConfig(rules, config, baseDir);
2285
2518
  case "geminicli":
@@ -2410,6 +2643,7 @@ var path4 = __toESM(require("path"), 1);
2410
2643
  init_augmentcode();
2411
2644
  init_claudecode();
2412
2645
  init_cline();
2646
+ init_codexcli();
2413
2647
  init_copilot();
2414
2648
  init_cursor();
2415
2649
  init_geminicli();
@@ -2483,6 +2717,11 @@ async function generateMcpConfigs(projectRoot, baseDir, targetTools) {
2483
2717
  path: path4.join(targetRoot, ".cline", "mcp.json"),
2484
2718
  generate: () => generateClineMcp(config)
2485
2719
  },
2720
+ {
2721
+ tool: "codexcli-project",
2722
+ path: path4.join(targetRoot, ".codex", "mcp-config.json"),
2723
+ generate: () => generateCodexMcp(config)
2724
+ },
2486
2725
  {
2487
2726
  tool: "gemini-project",
2488
2727
  path: path4.join(targetRoot, ".gemini", "settings.json"),
@@ -2518,7 +2757,7 @@ async function generateMcpConfigs(projectRoot, baseDir, targetTools) {
2518
2757
  try {
2519
2758
  const content = generator.generate();
2520
2759
  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")) {
2760
+ 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
2761
  if (!parsed.mcpServers || Object.keys(parsed.mcpServers).length === 0) {
2523
2762
  results.push({
2524
2763
  tool: generator.tool,
@@ -2743,6 +2982,8 @@ var gitignoreCommand = async () => {
2743
2982
  "**/.clineignore",
2744
2983
  "**/CLAUDE.md",
2745
2984
  "**/.claude/memories/",
2985
+ "**/codex.md",
2986
+ "**/.codexignore",
2746
2987
  "**/.roo/rules/",
2747
2988
  "**/.rooignore",
2748
2989
  "**/.copilotignore",
@@ -2761,6 +3002,7 @@ var gitignoreCommand = async () => {
2761
3002
  "**/.cursor/mcp.json",
2762
3003
  "**/.cline/mcp.json",
2763
3004
  "**/.vscode/mcp.json",
3005
+ "**/.codex/mcp-config.json",
2764
3006
  "**/.gemini/settings.json",
2765
3007
  "**/.roo/mcp.json"
2766
3008
  ];
@@ -2793,7 +3035,7 @@ ${linesToAdd.join("\n")}
2793
3035
  };
2794
3036
 
2795
3037
  // src/core/importer.ts
2796
- var import_node_path19 = require("path");
3038
+ var import_node_path20 = require("path");
2797
3039
  var import_gray_matter5 = __toESM(require("gray-matter"), 1);
2798
3040
 
2799
3041
  // src/parsers/augmentcode.ts
@@ -3218,6 +3460,9 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
3218
3460
  });
3219
3461
  }
3220
3462
 
3463
+ // src/parsers/codexcli.ts
3464
+ var import_node_path17 = require("path");
3465
+
3221
3466
  // src/parsers/copilot.ts
3222
3467
  async function parseCopilotConfiguration(baseDir = process.cwd()) {
3223
3468
  return parseConfigurationFiles(baseDir, {
@@ -3239,7 +3484,7 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
3239
3484
  }
3240
3485
 
3241
3486
  // src/parsers/cursor.ts
3242
- var import_node_path17 = require("path");
3487
+ var import_node_path18 = require("path");
3243
3488
  var import_gray_matter4 = __toESM(require("gray-matter"), 1);
3244
3489
  var import_js_yaml = require("js-yaml");
3245
3490
  var import_mini7 = require("zod/mini");
@@ -3364,7 +3609,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
3364
3609
  const rules = [];
3365
3610
  let ignorePatterns;
3366
3611
  let mcpServers;
3367
- const cursorFilePath = (0, import_node_path17.join)(baseDir, ".cursorrules");
3612
+ const cursorFilePath = (0, import_node_path18.join)(baseDir, ".cursorrules");
3368
3613
  if (await fileExists(cursorFilePath)) {
3369
3614
  try {
3370
3615
  const rawContent = await readFileContent(cursorFilePath);
@@ -3385,20 +3630,20 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
3385
3630
  errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
3386
3631
  }
3387
3632
  }
3388
- const cursorRulesDir = (0, import_node_path17.join)(baseDir, ".cursor", "rules");
3633
+ const cursorRulesDir = (0, import_node_path18.join)(baseDir, ".cursor", "rules");
3389
3634
  if (await fileExists(cursorRulesDir)) {
3390
3635
  try {
3391
3636
  const { readdir: readdir2 } = await import("fs/promises");
3392
3637
  const files = await readdir2(cursorRulesDir);
3393
3638
  for (const file of files) {
3394
3639
  if (file.endsWith(".mdc")) {
3395
- const filePath = (0, import_node_path17.join)(cursorRulesDir, file);
3640
+ const filePath = (0, import_node_path18.join)(cursorRulesDir, file);
3396
3641
  try {
3397
3642
  const rawContent = await readFileContent(filePath);
3398
3643
  const parsed = (0, import_gray_matter4.default)(rawContent, customMatterOptions);
3399
3644
  const content = parsed.content.trim();
3400
3645
  if (content) {
3401
- const filename = (0, import_node_path17.basename)(file, ".mdc");
3646
+ const filename = (0, import_node_path18.basename)(file, ".mdc");
3402
3647
  const frontmatter = convertCursorMdcFrontmatter(parsed.data, filename);
3403
3648
  rules.push({
3404
3649
  frontmatter,
@@ -3421,7 +3666,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
3421
3666
  if (rules.length === 0) {
3422
3667
  errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
3423
3668
  }
3424
- const cursorIgnorePath = (0, import_node_path17.join)(baseDir, ".cursorignore");
3669
+ const cursorIgnorePath = (0, import_node_path18.join)(baseDir, ".cursorignore");
3425
3670
  if (await fileExists(cursorIgnorePath)) {
3426
3671
  try {
3427
3672
  const content = await readFileContent(cursorIgnorePath);
@@ -3434,7 +3679,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
3434
3679
  errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
3435
3680
  }
3436
3681
  }
3437
- const cursorMcpPath = (0, import_node_path17.join)(baseDir, ".cursor", "mcp.json");
3682
+ const cursorMcpPath = (0, import_node_path18.join)(baseDir, ".cursor", "mcp.json");
3438
3683
  if (await fileExists(cursorMcpPath)) {
3439
3684
  try {
3440
3685
  const content = await readFileContent(cursorMcpPath);
@@ -3483,11 +3728,11 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
3483
3728
  }
3484
3729
 
3485
3730
  // src/parsers/junie.ts
3486
- var import_node_path18 = require("path");
3731
+ var import_node_path19 = require("path");
3487
3732
  async function parseJunieConfiguration(baseDir = process.cwd()) {
3488
3733
  const errors = [];
3489
3734
  const rules = [];
3490
- const guidelinesPath = (0, import_node_path18.join)(baseDir, ".junie", "guidelines.md");
3735
+ const guidelinesPath = (0, import_node_path19.join)(baseDir, ".junie", "guidelines.md");
3491
3736
  if (!await fileExists(guidelinesPath)) {
3492
3737
  errors.push(".junie/guidelines.md file not found");
3493
3738
  return { rules, errors };
@@ -3622,7 +3867,7 @@ async function importConfiguration(options) {
3622
3867
  if (rules.length === 0 && !ignorePatterns && !mcpServers) {
3623
3868
  return { success: false, rulesCreated: 0, errors };
3624
3869
  }
3625
- const rulesDirPath = (0, import_node_path19.join)(baseDir, rulesDir);
3870
+ const rulesDirPath = (0, import_node_path20.join)(baseDir, rulesDir);
3626
3871
  try {
3627
3872
  const { mkdir: mkdir3 } = await import("fs/promises");
3628
3873
  await mkdir3(rulesDirPath, { recursive: true });
@@ -3636,7 +3881,7 @@ async function importConfiguration(options) {
3636
3881
  try {
3637
3882
  const baseFilename = rule.filename;
3638
3883
  const filename = await generateUniqueFilename(rulesDirPath, baseFilename);
3639
- const filePath = (0, import_node_path19.join)(rulesDirPath, `${filename}.md`);
3884
+ const filePath = (0, import_node_path20.join)(rulesDirPath, `${filename}.md`);
3640
3885
  const content = generateRuleFileContent(rule);
3641
3886
  await writeFileContent(filePath, content);
3642
3887
  rulesCreated++;
@@ -3651,7 +3896,7 @@ async function importConfiguration(options) {
3651
3896
  let ignoreFileCreated = false;
3652
3897
  if (ignorePatterns && ignorePatterns.length > 0) {
3653
3898
  try {
3654
- const rulesyncignorePath = (0, import_node_path19.join)(baseDir, ".rulesyncignore");
3899
+ const rulesyncignorePath = (0, import_node_path20.join)(baseDir, ".rulesyncignore");
3655
3900
  const ignoreContent = `${ignorePatterns.join("\n")}
3656
3901
  `;
3657
3902
  await writeFileContent(rulesyncignorePath, ignoreContent);
@@ -3667,7 +3912,7 @@ async function importConfiguration(options) {
3667
3912
  let mcpFileCreated = false;
3668
3913
  if (mcpServers && Object.keys(mcpServers).length > 0) {
3669
3914
  try {
3670
- const mcpPath = (0, import_node_path19.join)(baseDir, rulesDir, ".mcp.json");
3915
+ const mcpPath = (0, import_node_path20.join)(baseDir, rulesDir, ".mcp.json");
3671
3916
  const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
3672
3917
  `;
3673
3918
  await writeFileContent(mcpPath, mcpContent);
@@ -3695,7 +3940,7 @@ function generateRuleFileContent(rule) {
3695
3940
  async function generateUniqueFilename(rulesDir, baseFilename) {
3696
3941
  let filename = baseFilename;
3697
3942
  let counter = 1;
3698
- while (await fileExists((0, import_node_path19.join)(rulesDir, `${filename}.md`))) {
3943
+ while (await fileExists((0, import_node_path20.join)(rulesDir, `${filename}.md`))) {
3699
3944
  filename = `${baseFilename}-${counter}`;
3700
3945
  counter++;
3701
3946
  }
@@ -3762,7 +4007,7 @@ async function importCommand(options = {}) {
3762
4007
  }
3763
4008
 
3764
4009
  // src/cli/commands/init.ts
3765
- var import_node_path20 = require("path");
4010
+ var import_node_path21 = require("path");
3766
4011
  async function initCommand() {
3767
4012
  const aiRulesDir = ".rulesync";
3768
4013
  console.log("Initializing rulesync...");
@@ -3809,7 +4054,7 @@ globs: ["**/*"]
3809
4054
  - Follow single responsibility principle
3810
4055
  `
3811
4056
  };
3812
- const filepath = (0, import_node_path20.join)(aiRulesDir, sampleFile.filename);
4057
+ const filepath = (0, import_node_path21.join)(aiRulesDir, sampleFile.filename);
3813
4058
  if (!await fileExists(filepath)) {
3814
4059
  await writeFileContent(filepath, sampleFile.content);
3815
4060
  console.log(`Created ${filepath}`);
@@ -3953,12 +4198,12 @@ async function watchCommand() {
3953
4198
 
3954
4199
  // src/cli/index.ts
3955
4200
  var program = new import_commander.Command();
3956
- program.name("rulesync").description("Unified AI rules management CLI tool").version("0.53.0");
4201
+ program.name("rulesync").description("Unified AI rules management CLI tool").version("0.54.0");
3957
4202
  program.command("init").description("Initialize rulesync in current directory").action(initCommand);
3958
4203
  program.command("add <filename>").description("Add a new rule file").action(addCommand);
3959
4204
  program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
3960
4205
  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(
4206
+ 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
4207
  "-b, --base-dir <paths>",
3963
4208
  "Base directories to generate files (comma-separated for multiple paths)"
3964
4209
  ).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 +4213,7 @@ program.command("generate").description("Generate configuration files for AI too
3968
4213
  if (options.copilot) tools.push("copilot");
3969
4214
  if (options.cursor) tools.push("cursor");
3970
4215
  if (options.cline) tools.push("cline");
4216
+ if (options.codexcli) tools.push("codexcli");
3971
4217
  if (options.claudecode) tools.push("claudecode");
3972
4218
  if (options.roo) tools.push("roo");
3973
4219
  if (options.geminicli) tools.push("geminicli");