rulesync 0.28.0 → 0.31.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 CHANGED
@@ -3,17 +3,19 @@
3
3
  [![CI](https://github.com/dyoshikawa/rulesync/actions/workflows/ci.yml/badge.svg)](https://github.com/dyoshikawa/rulesync/actions/workflows/ci.yml)
4
4
  [![npm version](https://badge.fury.io/js/rulesync.svg)](https://www.npmjs.com/package/rulesync)
5
5
 
6
- 統一されたAIルールファイル(`.rulesync/*.md`)から、様々なAI開発ツール用の設定ファイルを自動生成するNode.js CLIツールです。
6
+ 統一されたAIルールファイル(`.rulesync/*.md`)から、様々なAI開発ツール用の設定ファイルを自動生成するNode.js CLIツールです。既存のAIツール設定を統一形式にインポートすることも可能です。
7
7
 
8
8
  [English](./README.md) | **日本語**
9
9
 
10
10
  ## 対応ツール
11
11
 
12
+ rulesyncは以下のAI開発ツールの**生成**と**インポート**の両方をサポートしています:
13
+
12
14
  - **GitHub Copilot Custom Instructions** (`.github/copilot-instructions.md` + `.github/instructions/*.instructions.md`)
13
- - **Cursor Project Rules** (`.cursor/rules/*.mdc`)
14
- - **Cline Rules** (`.clinerules/*.md`)
15
+ - **Cursor Project Rules** (`.cursor/rules/*.mdc` + `.cursorrules`)
16
+ - **Cline Rules** (`.clinerules/*.md` + `.cline/instructions.md`)
15
17
  - **Claude Code Memory** (`./CLAUDE.md` + `.claude/memories/*.md`)
16
- - **Roo Code Rules** (`.roo/rules/*.md`)
18
+ - **Roo Code Rules** (`.roo/rules/*.md` + `.roo/instructions.md`)
17
19
 
18
20
  ## インストール
19
21
 
@@ -53,11 +55,19 @@ yarn global add rulesync
53
55
 
54
56
  ### AIツール設定を持つ既存プロジェクト
55
57
 
56
- 既にAIツールの設定がある場合、それらをインポートできます:
58
+ 既にAIツールの設定がある場合、それらをrulesync形式にインポートできます:
57
59
 
58
60
  1. **既存設定をインポート:**
59
61
  ```bash
60
- npx rulesync import --claude --cursor --copilot
62
+ # 複数のツールから一度にインポート
63
+ npx rulesync import --claudecode --cursor --copilot
64
+
65
+ # または特定のツールからインポート
66
+ npx rulesync import --claudecode # CLAUDE.mdと.claude/memories/*.mdから
67
+ npx rulesync import --cursor # .cursorrulesと.cursor/rules/*.mdcから
68
+ npx rulesync import --copilot # .github/copilot-instructions.mdから
69
+ npx rulesync import --cline # .cline/instructions.mdから
70
+ npx rulesync import --roo # .roo/instructions.mdから
61
71
  ```
62
72
 
63
73
  2. **`.rulesync/`ディレクトリのインポートされたルールを確認・編集**
@@ -172,7 +182,7 @@ npx rulesync generate
172
182
  npx rulesync generate --copilot
173
183
  npx rulesync generate --cursor
174
184
  npx rulesync generate --cline
175
- npx rulesync generate --claude
185
+ npx rulesync generate --claudecode
176
186
  npx rulesync generate --roo
177
187
 
178
188
  # クリーンビルド(既存ファイルを最初に削除)
@@ -195,7 +205,7 @@ npx rulesync generate --base-dir ./apps/web,./apps/api,./packages/shared
195
205
 
196
206
  - `--delete`: 新しいファイルを作成する前に既存の生成済みファイルをすべて削除
197
207
  - `--verbose`: 生成プロセス中に詳細出力を表示
198
- - `--copilot`, `--cursor`, `--cline`, `--claude`, `--roo`: 指定されたツールのみ生成
208
+ - `--copilot`, `--cursor`, `--cline`, `--claudecode`, `--roo`: 指定されたツールのみ生成
199
209
  - `--base-dir <paths>`: 指定されたベースディレクトリに設定ファイルを生成(複数パスの場合はカンマ区切り)。異なるプロジェクトディレクトリにツール固有の設定を生成したいmonorepoセットアップに便利。
200
210
 
201
211
  ### 4. 既存設定のインポート
@@ -204,25 +214,27 @@ npx rulesync generate --base-dir ./apps/web,./apps/api,./packages/shared
204
214
 
205
215
  ```bash
206
216
  # 既存のAIツール設定からインポート
207
- npx rulesync import --claude # CLAUDE.mdからインポート
208
- npx rulesync import --cursor # .cursorrulesからインポート
209
- npx rulesync import --copilot # .github/copilot-instructions.mdからインポート
210
- npx rulesync import --cline # .cline/instructions.mdからインポート
211
- npx rulesync import --roo # .roo/instructions.mdからインポート
217
+ npx rulesync import --claudecode # CLAUDE.mdと.claude/memories/*.mdからインポート
218
+ npx rulesync import --cursor # .cursorrulesと.cursor/rules/*.mdからインポート
219
+ npx rulesync import --copilot # .github/copilot-instructions.mdと.github/instructions/*.instructions.mdからインポート
220
+ npx rulesync import --cline # .cline/instructions.mdからインポート
221
+ npx rulesync import --roo # .roo/instructions.mdからインポート
212
222
 
213
223
  # 複数のツールからインポート
214
- npx rulesync import --claude --cursor --copilot
224
+ npx rulesync import --claudecode --cursor --copilot
215
225
 
216
226
  # インポート時の詳細出力
217
- npx rulesync import --claude --verbose
227
+ npx rulesync import --claudecode --verbose
218
228
  ```
219
229
 
220
230
  importコマンドの動作:
221
- - AIツールの既存設定ファイルをパース
222
- - 適切なフロントマターを付けてrulesync形式に変換
223
- - インポートしたコンテンツで新しい`.rulesync/*.md`ファイルを作成
224
- - ファイル名の競合を避けるためツール固有のプレフィックスを使用(例:`claude__overview.md`)
231
+ - カスタムパーサーを使用して各AIツールの既存設定ファイルをパース
232
+ - 適切なフロントマターメタデータを付けてrulesync形式に変換
233
+ - インポートしたコンテンツと適切なルール分類で新しい`.rulesync/*.md`ファイルを作成
234
+ - ファイル名の競合を避けるためツール固有のプレフィックスを使用(例:`claudecode-overview.md`、`cursor-custom-rules.md`)
225
235
  - 競合が発生した場合はユニークなファイル名を生成
236
+ - YAMLフロントマター付きのCursorのMDCファイルなど複雑なフォーマットをサポート
237
+ - 複数ファイルのインポート(例:`.claude/memories/`ディレクトリのすべてのファイル)に対応
226
238
 
227
239
  ### 5. その他のコマンド
228
240
 
package/README.md CHANGED
@@ -3,17 +3,19 @@
3
3
  [![CI](https://github.com/dyoshikawa/rulesync/actions/workflows/ci.yml/badge.svg)](https://github.com/dyoshikawa/rulesync/actions/workflows/ci.yml)
4
4
  [![npm version](https://badge.fury.io/js/rulesync.svg)](https://www.npmjs.com/package/rulesync)
5
5
 
6
- A Node.js CLI tool that automatically generates configuration files for various AI development tools from unified AI rule files (`.rulesync/*.md`).
6
+ A Node.js CLI tool that automatically generates configuration files for various AI development tools from unified AI rule files (`.rulesync/*.md`). Also imports existing AI tool configurations into the unified format.
7
7
 
8
8
  **English** | [日本語](./README.ja.md)
9
9
 
10
10
  ## Supported Tools
11
11
 
12
+ rulesync supports both **generation** and **import** for the following AI development tools:
13
+
12
14
  - **GitHub Copilot Custom Instructions** (`.github/copilot-instructions.md` + `.github/instructions/*.instructions.md`)
13
- - **Cursor Project Rules** (`.cursor/rules/*.mdc`)
14
- - **Cline Rules** (`.clinerules/*.md`)
15
+ - **Cursor Project Rules** (`.cursor/rules/*.mdc` + `.cursorrules`)
16
+ - **Cline Rules** (`.clinerules/*.md` + `.cline/instructions.md`)
15
17
  - **Claude Code Memory** (`./CLAUDE.md` + `.claude/memories/*.md`)
16
- - **Roo Code Rules** (`.roo/rules/*.md`)
18
+ - **Roo Code Rules** (`.roo/rules/*.md` + `.roo/instructions.md`)
17
19
 
18
20
  ## Installation
19
21
 
@@ -53,11 +55,19 @@ yarn global add rulesync
53
55
 
54
56
  ### Existing Project with AI Tool Configurations
55
57
 
56
- If you already have AI tool configurations, you can import them:
58
+ If you already have AI tool configurations, you can import them into rulesync format:
57
59
 
58
60
  1. **Import existing configurations:**
59
61
  ```bash
60
- npx rulesync import --claude --cursor --copilot
62
+ # Import from multiple tools at once
63
+ npx rulesync import --claudecode --cursor --copilot
64
+
65
+ # Or import from specific tools
66
+ npx rulesync import --claudecode # From CLAUDE.md and .claude/memories/*.md
67
+ npx rulesync import --cursor # From .cursorrules and .cursor/rules/*.mdc
68
+ npx rulesync import --copilot # From .github/copilot-instructions.md
69
+ npx rulesync import --cline # From .cline/instructions.md
70
+ npx rulesync import --roo # From .roo/instructions.md
61
71
  ```
62
72
 
63
73
  2. **Review and edit** the imported rules in `.rulesync/` directory
@@ -172,7 +182,7 @@ npx rulesync generate
172
182
  npx rulesync generate --copilot
173
183
  npx rulesync generate --cursor
174
184
  npx rulesync generate --cline
175
- npx rulesync generate --claude
185
+ npx rulesync generate --claudecode
176
186
  npx rulesync generate --roo
177
187
 
178
188
  # Clean build (delete existing files first)
@@ -195,7 +205,7 @@ npx rulesync generate --base-dir ./apps/web,./apps/api,./packages/shared
195
205
 
196
206
  - `--delete`: Remove all existing generated files before creating new ones
197
207
  - `--verbose`: Show detailed output during generation process
198
- - `--copilot`, `--cursor`, `--cline`, `--claude`, `--roo`: Generate only for specified tools
208
+ - `--copilot`, `--cursor`, `--cline`, `--claudecode`, `--roo`: Generate only for specified tools
199
209
  - `--base-dir <paths>`: Generate configuration files in specified base directories (comma-separated for multiple paths). Useful for monorepo setups where you want to generate tool-specific configurations in different project directories.
200
210
 
201
211
  ### 4. Import Existing Configurations
@@ -204,25 +214,27 @@ If you already have AI tool configurations in your project, you can import them
204
214
 
205
215
  ```bash
206
216
  # Import from existing AI tool configurations
207
- npx rulesync import --claude # Import from CLAUDE.md
208
- npx rulesync import --cursor # Import from .cursorrules
209
- npx rulesync import --copilot # Import from .github/copilot-instructions.md
210
- npx rulesync import --cline # Import from .cline/instructions.md
211
- npx rulesync import --roo # Import from .roo/instructions.md
217
+ npx rulesync import --claudecode # Import from CLAUDE.md and .claude/memories/*.md
218
+ npx rulesync import --cursor # Import from .cursorrules and .cursor/rules/*.md
219
+ npx rulesync import --copilot # Import from .github/copilot-instructions.md and .github/instructions/*.instructions.md
220
+ npx rulesync import --cline # Import from .cline/instructions.md
221
+ npx rulesync import --roo # Import from .roo/instructions.md
212
222
 
213
223
  # Import from multiple tools
214
- npx rulesync import --claude --cursor --copilot
224
+ npx rulesync import --claudecode --cursor --copilot
215
225
 
216
226
  # Verbose output during import
217
- npx rulesync import --claude --verbose
227
+ npx rulesync import --claudecode --verbose
218
228
  ```
219
229
 
220
230
  The import command will:
221
- - Parse existing configuration files from each AI tool
222
- - Convert them to rulesync format with appropriate frontmatter
223
- - Create new `.rulesync/*.md` files with imported content
224
- - Use tool-specific prefixes to avoid filename conflicts (e.g., `claude__overview.md`)
231
+ - Parse existing configuration files from each AI tool using custom parsers
232
+ - Convert them to rulesync format with appropriate frontmatter metadata
233
+ - Create new `.rulesync/*.md` files with imported content and proper rule categorization
234
+ - Use tool-specific prefixes to avoid filename conflicts (e.g., `claudecode-overview.md`, `cursor-custom-rules.md`)
225
235
  - Generate unique filenames if conflicts occur
236
+ - Support complex formats like Cursor's MDC files with YAML frontmatter
237
+ - Handle multiple file imports (e.g., all files from `.claude/memories/` directory)
226
238
 
227
239
  ### 5. Other Commands
228
240
 
package/dist/index.js CHANGED
@@ -38,11 +38,11 @@ function getDefaultConfig() {
38
38
  copilot: ".github/instructions",
39
39
  cursor: ".cursor/rules",
40
40
  cline: ".clinerules",
41
- claude: ".",
41
+ claudecode: ".",
42
42
  roo: ".roo/rules"
43
43
  },
44
44
  watchEnabled: false,
45
- defaultTargets: ["copilot", "cursor", "cline", "claude", "roo"]
45
+ defaultTargets: ["copilot", "cursor", "cline", "claudecode", "roo"]
46
46
  };
47
47
  }
48
48
  function resolveTargets(targets, config) {
@@ -88,23 +88,23 @@ async function addCommand(filename) {
88
88
  }
89
89
  }
90
90
 
91
- // src/generators/claude.ts
91
+ // src/generators/claudecode.ts
92
92
  var import_node_path2 = require("path");
93
- async function generateClaudeConfig(rules, config, baseDir) {
93
+ async function generateClaudecodeConfig(rules, config, baseDir) {
94
94
  const outputs = [];
95
95
  const rootRules = rules.filter((r) => r.frontmatter.root === true);
96
96
  const detailRules = rules.filter((r) => r.frontmatter.root === false);
97
97
  const claudeMdContent = generateClaudeMarkdown(rootRules, detailRules);
98
- const claudeOutputDir = baseDir ? (0, import_node_path2.join)(baseDir, config.outputPaths.claude) : config.outputPaths.claude;
98
+ const claudeOutputDir = baseDir ? (0, import_node_path2.join)(baseDir, config.outputPaths.claudecode) : config.outputPaths.claudecode;
99
99
  outputs.push({
100
- tool: "claude",
100
+ tool: "claudecode",
101
101
  filepath: (0, import_node_path2.join)(claudeOutputDir, "CLAUDE.md"),
102
102
  content: claudeMdContent
103
103
  });
104
104
  for (const rule of detailRules) {
105
105
  const memoryContent = generateMemoryFile(rule);
106
106
  outputs.push({
107
- tool: "claude",
107
+ tool: "claudecode",
108
108
  filepath: (0, import_node_path2.join)(claudeOutputDir, ".claude", "memories", `${rule.filename}.md`),
109
109
  content: memoryContent
110
110
  });
@@ -350,8 +350,8 @@ async function generateForTool(tool, rules, config, baseDir) {
350
350
  return generateCursorConfig(rules, config, baseDir);
351
351
  case "cline":
352
352
  return generateClineConfig(rules, config, baseDir);
353
- case "claude":
354
- return await generateClaudeConfig(rules, config, baseDir);
353
+ case "claudecode":
354
+ return await generateClaudecodeConfig(rules, config, baseDir);
355
355
  case "roo":
356
356
  return generateRooConfig(rules, config, baseDir);
357
357
  default:
@@ -561,7 +561,7 @@ async function generateCommand(options = {}) {
561
561
  case "cline":
562
562
  deleteTasks.push(removeDirectory(config.outputPaths.cline));
563
563
  break;
564
- case "claude":
564
+ case "claudecode":
565
565
  deleteTasks.push(removeClaudeGeneratedFiles());
566
566
  break;
567
567
  case "roo":
@@ -612,14 +612,6 @@ var gitignoreCommand = async () => {
612
612
  const gitignorePath = (0, import_node_path9.join)(process.cwd(), ".gitignore");
613
613
  const rulesFilesToIgnore = [
614
614
  "# Generated by rulesync - AI tool configuration files",
615
- ".github/copilot-instructions.md",
616
- ".github/instructions/",
617
- ".cursor/rules/",
618
- ".clinerules/",
619
- "CLAUDE.md",
620
- ".claude/memories/",
621
- ".roo/rules/",
622
- "# Support for --base-dir option (any depth)",
623
615
  "**/.github/copilot-instructions.md",
624
616
  "**/.github/instructions/",
625
617
  "**/.cursor/rules/",
@@ -658,9 +650,9 @@ ${linesToAdd.join("\n")}
658
650
 
659
651
  // src/core/importer.ts
660
652
  var import_node_path15 = require("path");
661
- var import_gray_matter2 = __toESM(require("gray-matter"));
653
+ var import_gray_matter4 = __toESM(require("gray-matter"));
662
654
 
663
- // src/parsers/claude.ts
655
+ // src/parsers/claudecode.ts
664
656
  var import_node_path10 = require("path");
665
657
  async function parseClaudeConfiguration(baseDir = process.cwd()) {
666
658
  const errors = [];
@@ -704,7 +696,7 @@ function parseClaudeMainFile(content, filepath) {
704
696
  }
705
697
  const frontmatter = {
706
698
  root: false,
707
- targets: ["claude"],
699
+ targets: ["claudecode"],
708
700
  description: "Main Claude Code configuration",
709
701
  globs: ["**/*"]
710
702
  };
@@ -728,7 +720,7 @@ async function parseClaudeMemoryFiles(memoryDir) {
728
720
  const filename = (0, import_node_path10.basename)(file, ".md");
729
721
  const frontmatter = {
730
722
  root: false,
731
- targets: ["claude"],
723
+ targets: ["claudecode"],
732
724
  description: `Memory file: ${filename}`,
733
725
  globs: ["**/*"]
734
726
  };
@@ -781,66 +773,166 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
781
773
 
782
774
  // src/parsers/copilot.ts
783
775
  var import_node_path12 = require("path");
776
+ var import_gray_matter2 = __toESM(require("gray-matter"));
784
777
  async function parseCopilotConfiguration(baseDir = process.cwd()) {
785
778
  const errors = [];
786
779
  const rules = [];
787
780
  const copilotFilePath = (0, import_node_path12.join)(baseDir, ".github", "copilot-instructions.md");
788
- if (!await fileExists(copilotFilePath)) {
789
- errors.push(".github/copilot-instructions.md file not found");
790
- return { rules, errors };
781
+ if (await fileExists(copilotFilePath)) {
782
+ try {
783
+ const rawContent = await readFileContent(copilotFilePath);
784
+ const parsed = (0, import_gray_matter2.default)(rawContent);
785
+ const content = parsed.content.trim();
786
+ if (content) {
787
+ const frontmatter = {
788
+ root: false,
789
+ targets: ["copilot"],
790
+ description: "GitHub Copilot instructions",
791
+ globs: ["**/*"]
792
+ };
793
+ rules.push({
794
+ frontmatter,
795
+ content,
796
+ filename: "copilot-instructions",
797
+ filepath: copilotFilePath
798
+ });
799
+ }
800
+ } catch (error) {
801
+ const errorMessage = error instanceof Error ? error.message : String(error);
802
+ errors.push(`Failed to parse copilot-instructions.md: ${errorMessage}`);
803
+ }
791
804
  }
792
- try {
793
- const content = await readFileContent(copilotFilePath);
794
- if (content.trim()) {
795
- const frontmatter = {
796
- root: false,
797
- targets: ["copilot"],
798
- description: "GitHub Copilot instructions",
799
- globs: ["**/*"]
800
- };
801
- rules.push({
802
- frontmatter,
803
- content: content.trim(),
804
- filename: "copilot-instructions",
805
- filepath: copilotFilePath
806
- });
805
+ const instructionsDir = (0, import_node_path12.join)(baseDir, ".github", "instructions");
806
+ if (await fileExists(instructionsDir)) {
807
+ try {
808
+ const { readdir: readdir2 } = await import("fs/promises");
809
+ const files = await readdir2(instructionsDir);
810
+ for (const file of files) {
811
+ if (file.endsWith(".instructions.md")) {
812
+ const filePath = (0, import_node_path12.join)(instructionsDir, file);
813
+ const rawContent = await readFileContent(filePath);
814
+ const parsed = (0, import_gray_matter2.default)(rawContent);
815
+ const content = parsed.content.trim();
816
+ if (content) {
817
+ const filename = (0, import_node_path12.basename)(file, ".instructions.md");
818
+ const frontmatter = {
819
+ root: false,
820
+ targets: ["copilot"],
821
+ description: `Copilot instruction: ${filename}`,
822
+ globs: ["**/*"]
823
+ };
824
+ rules.push({
825
+ frontmatter,
826
+ content,
827
+ filename: `copilot-${filename}`,
828
+ filepath: filePath
829
+ });
830
+ }
831
+ }
832
+ }
833
+ } catch (error) {
834
+ const errorMessage = error instanceof Error ? error.message : String(error);
835
+ errors.push(`Failed to parse .github/instructions files: ${errorMessage}`);
807
836
  }
808
- } catch (error) {
809
- const errorMessage = error instanceof Error ? error.message : String(error);
810
- errors.push(`Failed to parse Copilot configuration: ${errorMessage}`);
837
+ }
838
+ if (rules.length === 0) {
839
+ errors.push(
840
+ "No Copilot configuration files found (.github/copilot-instructions.md or .github/instructions/*.instructions.md)"
841
+ );
811
842
  }
812
843
  return { rules, errors };
813
844
  }
814
845
 
815
846
  // src/parsers/cursor.ts
816
847
  var import_node_path13 = require("path");
848
+ var import_gray_matter3 = __toESM(require("gray-matter"));
849
+ var import_js_yaml = __toESM(require("js-yaml"));
850
+ var customMatterOptions = {
851
+ engines: {
852
+ yaml: {
853
+ parse: (str) => {
854
+ try {
855
+ const preprocessed = str.replace(/^(\s*globs:\s*)\*\s*$/gm, '$1"*"');
856
+ return import_js_yaml.default.load(preprocessed, { schema: import_js_yaml.default.DEFAULT_SCHEMA });
857
+ } catch (error) {
858
+ try {
859
+ return import_js_yaml.default.load(str, { schema: import_js_yaml.default.FAILSAFE_SCHEMA });
860
+ } catch {
861
+ throw error;
862
+ }
863
+ }
864
+ }
865
+ }
866
+ }
867
+ };
817
868
  async function parseCursorConfiguration(baseDir = process.cwd()) {
818
869
  const errors = [];
819
870
  const rules = [];
820
871
  const cursorFilePath = (0, import_node_path13.join)(baseDir, ".cursorrules");
821
- if (!await fileExists(cursorFilePath)) {
822
- errors.push(".cursorrules file not found");
823
- return { rules, errors };
872
+ if (await fileExists(cursorFilePath)) {
873
+ try {
874
+ const rawContent = await readFileContent(cursorFilePath);
875
+ const parsed = (0, import_gray_matter3.default)(rawContent, customMatterOptions);
876
+ const content = parsed.content.trim();
877
+ if (content) {
878
+ const frontmatter = {
879
+ root: false,
880
+ targets: ["cursor"],
881
+ description: "Cursor IDE configuration rules",
882
+ globs: ["**/*"]
883
+ };
884
+ rules.push({
885
+ frontmatter,
886
+ content,
887
+ filename: "cursor-rules",
888
+ filepath: cursorFilePath
889
+ });
890
+ }
891
+ } catch (error) {
892
+ const errorMessage = error instanceof Error ? error.message : String(error);
893
+ errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
894
+ }
824
895
  }
825
- try {
826
- const content = await readFileContent(cursorFilePath);
827
- if (content.trim()) {
828
- const frontmatter = {
829
- root: false,
830
- targets: ["cursor"],
831
- description: "Cursor IDE configuration rules",
832
- globs: ["**/*"]
833
- };
834
- rules.push({
835
- frontmatter,
836
- content: content.trim(),
837
- filename: "cursor-rules",
838
- filepath: cursorFilePath
839
- });
896
+ const cursorRulesDir = (0, import_node_path13.join)(baseDir, ".cursor", "rules");
897
+ if (await fileExists(cursorRulesDir)) {
898
+ try {
899
+ const { readdir: readdir2 } = await import("fs/promises");
900
+ const files = await readdir2(cursorRulesDir);
901
+ for (const file of files) {
902
+ if (file.endsWith(".mdc")) {
903
+ const filePath = (0, import_node_path13.join)(cursorRulesDir, file);
904
+ try {
905
+ const rawContent = await readFileContent(filePath);
906
+ const parsed = (0, import_gray_matter3.default)(rawContent, customMatterOptions);
907
+ const content = parsed.content.trim();
908
+ if (content) {
909
+ const filename = (0, import_node_path13.basename)(file, ".mdc");
910
+ const frontmatter = {
911
+ root: false,
912
+ targets: ["cursor"],
913
+ description: `Cursor rule: ${filename}`,
914
+ globs: ["**/*"]
915
+ };
916
+ rules.push({
917
+ frontmatter,
918
+ content,
919
+ filename: `cursor-${filename}`,
920
+ filepath: filePath
921
+ });
922
+ }
923
+ } catch (error) {
924
+ const errorMessage = error instanceof Error ? error.message : String(error);
925
+ errors.push(`Failed to parse ${filePath}: ${errorMessage}`);
926
+ }
927
+ }
928
+ }
929
+ } catch (error) {
930
+ const errorMessage = error instanceof Error ? error.message : String(error);
931
+ errors.push(`Failed to parse .cursor/rules files: ${errorMessage}`);
840
932
  }
841
- } catch (error) {
842
- const errorMessage = error instanceof Error ? error.message : String(error);
843
- errors.push(`Failed to parse Cursor configuration: ${errorMessage}`);
933
+ }
934
+ if (rules.length === 0) {
935
+ errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
844
936
  }
845
937
  return { rules, errors };
846
938
  }
@@ -888,7 +980,7 @@ async function importConfiguration(options) {
888
980
  }
889
981
  try {
890
982
  switch (tool) {
891
- case "claude": {
983
+ case "claudecode": {
892
984
  const claudeResult = await parseClaudeConfiguration(baseDir);
893
985
  rules = claudeResult.rules;
894
986
  errors.push(...claudeResult.errors);
@@ -963,7 +1055,7 @@ async function importConfiguration(options) {
963
1055
  };
964
1056
  }
965
1057
  function generateRuleFileContent(rule) {
966
- const frontmatter = import_gray_matter2.default.stringify("", rule.frontmatter);
1058
+ const frontmatter = import_gray_matter4.default.stringify("", rule.frontmatter);
967
1059
  return frontmatter + rule.content;
968
1060
  }
969
1061
  async function generateUniqueFilename(rulesDir, baseFilename) {
@@ -979,14 +1071,14 @@ async function generateUniqueFilename(rulesDir, baseFilename) {
979
1071
  // src/cli/commands/import.ts
980
1072
  async function importCommand(options = {}) {
981
1073
  const tools = [];
982
- if (options.claude) tools.push("claude");
1074
+ if (options.claudecode) tools.push("claudecode");
983
1075
  if (options.cursor) tools.push("cursor");
984
1076
  if (options.copilot) tools.push("copilot");
985
1077
  if (options.cline) tools.push("cline");
986
1078
  if (options.roo) tools.push("roo");
987
1079
  if (tools.length === 0) {
988
1080
  console.error(
989
- "\u274C Please specify at least one tool to import from (--claude, --cursor, --copilot, --cline, --roo)"
1081
+ "\u274C Please specify at least one tool to import from (--claudecode, --cursor, --copilot, --cline, --roo)"
990
1082
  );
991
1083
  process.exit(1);
992
1084
  }
@@ -1197,7 +1289,7 @@ async function statusCommand() {
1197
1289
  const nonRootRules = rules.length - rootRules;
1198
1290
  console.log(` - Root rules: ${rootRules}`);
1199
1291
  console.log(` - Non-root rules: ${nonRootRules}`);
1200
- const targetCounts = { copilot: 0, cursor: 0, cline: 0, claude: 0, roo: 0 };
1292
+ const targetCounts = { copilot: 0, cursor: 0, cline: 0, claudecode: 0, roo: 0 };
1201
1293
  for (const rule of rules) {
1202
1294
  const targets = rule.frontmatter.targets[0] === "*" ? config.defaultTargets : rule.frontmatter.targets;
1203
1295
  for (const target of targets) {
@@ -1210,7 +1302,7 @@ async function statusCommand() {
1210
1302
  console.log(` - Copilot: ${targetCounts.copilot} rules`);
1211
1303
  console.log(` - Cursor: ${targetCounts.cursor} rules`);
1212
1304
  console.log(` - Cline: ${targetCounts.cline} rules`);
1213
- console.log(` - Claude: ${targetCounts.claude} rules`);
1305
+ console.log(` - Claude Code: ${targetCounts.claudecode} rules`);
1214
1306
  console.log(` - Roo: ${targetCounts.roo} rules`);
1215
1307
  }
1216
1308
  console.log("\n\u{1F4E4} Generated files:");
@@ -1309,12 +1401,12 @@ async function watchCommand() {
1309
1401
 
1310
1402
  // src/cli/index.ts
1311
1403
  var program = new import_commander.Command();
1312
- program.name("rulesync").description("Unified AI rules management CLI tool").version("0.28.0");
1404
+ program.name("rulesync").description("Unified AI rules management CLI tool").version("0.31.0");
1313
1405
  program.command("init").description("Initialize rulesync in current directory").action(initCommand);
1314
1406
  program.command("add <filename>").description("Add a new rule file").action(addCommand);
1315
1407
  program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
1316
- program.command("import").description("Import configurations from AI tools to rulesync format").option("--claude", "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("-v, --verbose", "Verbose output").action(importCommand);
1317
- program.command("generate").description("Generate configuration files for AI tools").option("--copilot", "Generate only for GitHub Copilot").option("--cursor", "Generate only for Cursor").option("--cline", "Generate only for Cline").option("--claude", "Generate only for Claude Code").option("--roo", "Generate only for Roo Code").option("--delete", "Delete all existing files in output directories before generating").option(
1408
+ program.command("import").description("Import configurations from AI tools to rulesync format").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("-v, --verbose", "Verbose output").action(importCommand);
1409
+ program.command("generate").description("Generate configuration files for AI tools").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("--delete", "Delete all existing files in output directories before generating").option(
1318
1410
  "-b, --base-dir <paths>",
1319
1411
  "Base directories to generate files (comma-separated for multiple paths)"
1320
1412
  ).option("-v, --verbose", "Verbose output").action(async (options) => {
@@ -1322,7 +1414,7 @@ program.command("generate").description("Generate configuration files for AI too
1322
1414
  if (options.copilot) tools.push("copilot");
1323
1415
  if (options.cursor) tools.push("cursor");
1324
1416
  if (options.cline) tools.push("cline");
1325
- if (options.claude) tools.push("claude");
1417
+ if (options.claudecode) tools.push("claudecode");
1326
1418
  if (options.roo) tools.push("roo");
1327
1419
  const generateOptions = {
1328
1420
  verbose: options.verbose,
package/dist/index.mjs CHANGED
@@ -15,11 +15,11 @@ function getDefaultConfig() {
15
15
  copilot: ".github/instructions",
16
16
  cursor: ".cursor/rules",
17
17
  cline: ".clinerules",
18
- claude: ".",
18
+ claudecode: ".",
19
19
  roo: ".roo/rules"
20
20
  },
21
21
  watchEnabled: false,
22
- defaultTargets: ["copilot", "cursor", "cline", "claude", "roo"]
22
+ defaultTargets: ["copilot", "cursor", "cline", "claudecode", "roo"]
23
23
  };
24
24
  }
25
25
  function resolveTargets(targets, config) {
@@ -65,23 +65,23 @@ async function addCommand(filename) {
65
65
  }
66
66
  }
67
67
 
68
- // src/generators/claude.ts
68
+ // src/generators/claudecode.ts
69
69
  import { join } from "path";
70
- async function generateClaudeConfig(rules, config, baseDir) {
70
+ async function generateClaudecodeConfig(rules, config, baseDir) {
71
71
  const outputs = [];
72
72
  const rootRules = rules.filter((r) => r.frontmatter.root === true);
73
73
  const detailRules = rules.filter((r) => r.frontmatter.root === false);
74
74
  const claudeMdContent = generateClaudeMarkdown(rootRules, detailRules);
75
- const claudeOutputDir = baseDir ? join(baseDir, config.outputPaths.claude) : config.outputPaths.claude;
75
+ const claudeOutputDir = baseDir ? join(baseDir, config.outputPaths.claudecode) : config.outputPaths.claudecode;
76
76
  outputs.push({
77
- tool: "claude",
77
+ tool: "claudecode",
78
78
  filepath: join(claudeOutputDir, "CLAUDE.md"),
79
79
  content: claudeMdContent
80
80
  });
81
81
  for (const rule of detailRules) {
82
82
  const memoryContent = generateMemoryFile(rule);
83
83
  outputs.push({
84
- tool: "claude",
84
+ tool: "claudecode",
85
85
  filepath: join(claudeOutputDir, ".claude", "memories", `${rule.filename}.md`),
86
86
  content: memoryContent
87
87
  });
@@ -327,8 +327,8 @@ async function generateForTool(tool, rules, config, baseDir) {
327
327
  return generateCursorConfig(rules, config, baseDir);
328
328
  case "cline":
329
329
  return generateClineConfig(rules, config, baseDir);
330
- case "claude":
331
- return await generateClaudeConfig(rules, config, baseDir);
330
+ case "claudecode":
331
+ return await generateClaudecodeConfig(rules, config, baseDir);
332
332
  case "roo":
333
333
  return generateRooConfig(rules, config, baseDir);
334
334
  default:
@@ -538,7 +538,7 @@ async function generateCommand(options = {}) {
538
538
  case "cline":
539
539
  deleteTasks.push(removeDirectory(config.outputPaths.cline));
540
540
  break;
541
- case "claude":
541
+ case "claudecode":
542
542
  deleteTasks.push(removeClaudeGeneratedFiles());
543
543
  break;
544
544
  case "roo":
@@ -589,14 +589,6 @@ var gitignoreCommand = async () => {
589
589
  const gitignorePath = join7(process.cwd(), ".gitignore");
590
590
  const rulesFilesToIgnore = [
591
591
  "# Generated by rulesync - AI tool configuration files",
592
- ".github/copilot-instructions.md",
593
- ".github/instructions/",
594
- ".cursor/rules/",
595
- ".clinerules/",
596
- "CLAUDE.md",
597
- ".claude/memories/",
598
- ".roo/rules/",
599
- "# Support for --base-dir option (any depth)",
600
592
  "**/.github/copilot-instructions.md",
601
593
  "**/.github/instructions/",
602
594
  "**/.cursor/rules/",
@@ -635,9 +627,9 @@ ${linesToAdd.join("\n")}
635
627
 
636
628
  // src/core/importer.ts
637
629
  import { join as join13 } from "path";
638
- import matter2 from "gray-matter";
630
+ import matter4 from "gray-matter";
639
631
 
640
- // src/parsers/claude.ts
632
+ // src/parsers/claudecode.ts
641
633
  import { basename as basename2, join as join8 } from "path";
642
634
  async function parseClaudeConfiguration(baseDir = process.cwd()) {
643
635
  const errors = [];
@@ -681,7 +673,7 @@ function parseClaudeMainFile(content, filepath) {
681
673
  }
682
674
  const frontmatter = {
683
675
  root: false,
684
- targets: ["claude"],
676
+ targets: ["claudecode"],
685
677
  description: "Main Claude Code configuration",
686
678
  globs: ["**/*"]
687
679
  };
@@ -705,7 +697,7 @@ async function parseClaudeMemoryFiles(memoryDir) {
705
697
  const filename = basename2(file, ".md");
706
698
  const frontmatter = {
707
699
  root: false,
708
- targets: ["claude"],
700
+ targets: ["claudecode"],
709
701
  description: `Memory file: ${filename}`,
710
702
  globs: ["**/*"]
711
703
  };
@@ -757,67 +749,167 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
757
749
  }
758
750
 
759
751
  // src/parsers/copilot.ts
760
- import { join as join10 } from "path";
752
+ import { basename as basename3, join as join10 } from "path";
753
+ import matter2 from "gray-matter";
761
754
  async function parseCopilotConfiguration(baseDir = process.cwd()) {
762
755
  const errors = [];
763
756
  const rules = [];
764
757
  const copilotFilePath = join10(baseDir, ".github", "copilot-instructions.md");
765
- if (!await fileExists(copilotFilePath)) {
766
- errors.push(".github/copilot-instructions.md file not found");
767
- return { rules, errors };
758
+ if (await fileExists(copilotFilePath)) {
759
+ try {
760
+ const rawContent = await readFileContent(copilotFilePath);
761
+ const parsed = matter2(rawContent);
762
+ const content = parsed.content.trim();
763
+ if (content) {
764
+ const frontmatter = {
765
+ root: false,
766
+ targets: ["copilot"],
767
+ description: "GitHub Copilot instructions",
768
+ globs: ["**/*"]
769
+ };
770
+ rules.push({
771
+ frontmatter,
772
+ content,
773
+ filename: "copilot-instructions",
774
+ filepath: copilotFilePath
775
+ });
776
+ }
777
+ } catch (error) {
778
+ const errorMessage = error instanceof Error ? error.message : String(error);
779
+ errors.push(`Failed to parse copilot-instructions.md: ${errorMessage}`);
780
+ }
768
781
  }
769
- try {
770
- const content = await readFileContent(copilotFilePath);
771
- if (content.trim()) {
772
- const frontmatter = {
773
- root: false,
774
- targets: ["copilot"],
775
- description: "GitHub Copilot instructions",
776
- globs: ["**/*"]
777
- };
778
- rules.push({
779
- frontmatter,
780
- content: content.trim(),
781
- filename: "copilot-instructions",
782
- filepath: copilotFilePath
783
- });
782
+ const instructionsDir = join10(baseDir, ".github", "instructions");
783
+ if (await fileExists(instructionsDir)) {
784
+ try {
785
+ const { readdir: readdir2 } = await import("fs/promises");
786
+ const files = await readdir2(instructionsDir);
787
+ for (const file of files) {
788
+ if (file.endsWith(".instructions.md")) {
789
+ const filePath = join10(instructionsDir, file);
790
+ const rawContent = await readFileContent(filePath);
791
+ const parsed = matter2(rawContent);
792
+ const content = parsed.content.trim();
793
+ if (content) {
794
+ const filename = basename3(file, ".instructions.md");
795
+ const frontmatter = {
796
+ root: false,
797
+ targets: ["copilot"],
798
+ description: `Copilot instruction: ${filename}`,
799
+ globs: ["**/*"]
800
+ };
801
+ rules.push({
802
+ frontmatter,
803
+ content,
804
+ filename: `copilot-${filename}`,
805
+ filepath: filePath
806
+ });
807
+ }
808
+ }
809
+ }
810
+ } catch (error) {
811
+ const errorMessage = error instanceof Error ? error.message : String(error);
812
+ errors.push(`Failed to parse .github/instructions files: ${errorMessage}`);
784
813
  }
785
- } catch (error) {
786
- const errorMessage = error instanceof Error ? error.message : String(error);
787
- errors.push(`Failed to parse Copilot configuration: ${errorMessage}`);
814
+ }
815
+ if (rules.length === 0) {
816
+ errors.push(
817
+ "No Copilot configuration files found (.github/copilot-instructions.md or .github/instructions/*.instructions.md)"
818
+ );
788
819
  }
789
820
  return { rules, errors };
790
821
  }
791
822
 
792
823
  // src/parsers/cursor.ts
793
- import { join as join11 } from "path";
824
+ import { basename as basename4, join as join11 } from "path";
825
+ import matter3 from "gray-matter";
826
+ import yaml from "js-yaml";
827
+ var customMatterOptions = {
828
+ engines: {
829
+ yaml: {
830
+ parse: (str) => {
831
+ try {
832
+ const preprocessed = str.replace(/^(\s*globs:\s*)\*\s*$/gm, '$1"*"');
833
+ return yaml.load(preprocessed, { schema: yaml.DEFAULT_SCHEMA });
834
+ } catch (error) {
835
+ try {
836
+ return yaml.load(str, { schema: yaml.FAILSAFE_SCHEMA });
837
+ } catch {
838
+ throw error;
839
+ }
840
+ }
841
+ }
842
+ }
843
+ }
844
+ };
794
845
  async function parseCursorConfiguration(baseDir = process.cwd()) {
795
846
  const errors = [];
796
847
  const rules = [];
797
848
  const cursorFilePath = join11(baseDir, ".cursorrules");
798
- if (!await fileExists(cursorFilePath)) {
799
- errors.push(".cursorrules file not found");
800
- return { rules, errors };
849
+ if (await fileExists(cursorFilePath)) {
850
+ try {
851
+ const rawContent = await readFileContent(cursorFilePath);
852
+ const parsed = matter3(rawContent, customMatterOptions);
853
+ const content = parsed.content.trim();
854
+ if (content) {
855
+ const frontmatter = {
856
+ root: false,
857
+ targets: ["cursor"],
858
+ description: "Cursor IDE configuration rules",
859
+ globs: ["**/*"]
860
+ };
861
+ rules.push({
862
+ frontmatter,
863
+ content,
864
+ filename: "cursor-rules",
865
+ filepath: cursorFilePath
866
+ });
867
+ }
868
+ } catch (error) {
869
+ const errorMessage = error instanceof Error ? error.message : String(error);
870
+ errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
871
+ }
801
872
  }
802
- try {
803
- const content = await readFileContent(cursorFilePath);
804
- if (content.trim()) {
805
- const frontmatter = {
806
- root: false,
807
- targets: ["cursor"],
808
- description: "Cursor IDE configuration rules",
809
- globs: ["**/*"]
810
- };
811
- rules.push({
812
- frontmatter,
813
- content: content.trim(),
814
- filename: "cursor-rules",
815
- filepath: cursorFilePath
816
- });
873
+ const cursorRulesDir = join11(baseDir, ".cursor", "rules");
874
+ if (await fileExists(cursorRulesDir)) {
875
+ try {
876
+ const { readdir: readdir2 } = await import("fs/promises");
877
+ const files = await readdir2(cursorRulesDir);
878
+ for (const file of files) {
879
+ if (file.endsWith(".mdc")) {
880
+ const filePath = join11(cursorRulesDir, file);
881
+ try {
882
+ const rawContent = await readFileContent(filePath);
883
+ const parsed = matter3(rawContent, customMatterOptions);
884
+ const content = parsed.content.trim();
885
+ if (content) {
886
+ const filename = basename4(file, ".mdc");
887
+ const frontmatter = {
888
+ root: false,
889
+ targets: ["cursor"],
890
+ description: `Cursor rule: ${filename}`,
891
+ globs: ["**/*"]
892
+ };
893
+ rules.push({
894
+ frontmatter,
895
+ content,
896
+ filename: `cursor-${filename}`,
897
+ filepath: filePath
898
+ });
899
+ }
900
+ } catch (error) {
901
+ const errorMessage = error instanceof Error ? error.message : String(error);
902
+ errors.push(`Failed to parse ${filePath}: ${errorMessage}`);
903
+ }
904
+ }
905
+ }
906
+ } catch (error) {
907
+ const errorMessage = error instanceof Error ? error.message : String(error);
908
+ errors.push(`Failed to parse .cursor/rules files: ${errorMessage}`);
817
909
  }
818
- } catch (error) {
819
- const errorMessage = error instanceof Error ? error.message : String(error);
820
- errors.push(`Failed to parse Cursor configuration: ${errorMessage}`);
910
+ }
911
+ if (rules.length === 0) {
912
+ errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
821
913
  }
822
914
  return { rules, errors };
823
915
  }
@@ -865,7 +957,7 @@ async function importConfiguration(options) {
865
957
  }
866
958
  try {
867
959
  switch (tool) {
868
- case "claude": {
960
+ case "claudecode": {
869
961
  const claudeResult = await parseClaudeConfiguration(baseDir);
870
962
  rules = claudeResult.rules;
871
963
  errors.push(...claudeResult.errors);
@@ -940,7 +1032,7 @@ async function importConfiguration(options) {
940
1032
  };
941
1033
  }
942
1034
  function generateRuleFileContent(rule) {
943
- const frontmatter = matter2.stringify("", rule.frontmatter);
1035
+ const frontmatter = matter4.stringify("", rule.frontmatter);
944
1036
  return frontmatter + rule.content;
945
1037
  }
946
1038
  async function generateUniqueFilename(rulesDir, baseFilename) {
@@ -956,14 +1048,14 @@ async function generateUniqueFilename(rulesDir, baseFilename) {
956
1048
  // src/cli/commands/import.ts
957
1049
  async function importCommand(options = {}) {
958
1050
  const tools = [];
959
- if (options.claude) tools.push("claude");
1051
+ if (options.claudecode) tools.push("claudecode");
960
1052
  if (options.cursor) tools.push("cursor");
961
1053
  if (options.copilot) tools.push("copilot");
962
1054
  if (options.cline) tools.push("cline");
963
1055
  if (options.roo) tools.push("roo");
964
1056
  if (tools.length === 0) {
965
1057
  console.error(
966
- "\u274C Please specify at least one tool to import from (--claude, --cursor, --copilot, --cline, --roo)"
1058
+ "\u274C Please specify at least one tool to import from (--claudecode, --cursor, --copilot, --cline, --roo)"
967
1059
  );
968
1060
  process.exit(1);
969
1061
  }
@@ -1174,7 +1266,7 @@ async function statusCommand() {
1174
1266
  const nonRootRules = rules.length - rootRules;
1175
1267
  console.log(` - Root rules: ${rootRules}`);
1176
1268
  console.log(` - Non-root rules: ${nonRootRules}`);
1177
- const targetCounts = { copilot: 0, cursor: 0, cline: 0, claude: 0, roo: 0 };
1269
+ const targetCounts = { copilot: 0, cursor: 0, cline: 0, claudecode: 0, roo: 0 };
1178
1270
  for (const rule of rules) {
1179
1271
  const targets = rule.frontmatter.targets[0] === "*" ? config.defaultTargets : rule.frontmatter.targets;
1180
1272
  for (const target of targets) {
@@ -1187,7 +1279,7 @@ async function statusCommand() {
1187
1279
  console.log(` - Copilot: ${targetCounts.copilot} rules`);
1188
1280
  console.log(` - Cursor: ${targetCounts.cursor} rules`);
1189
1281
  console.log(` - Cline: ${targetCounts.cline} rules`);
1190
- console.log(` - Claude: ${targetCounts.claude} rules`);
1282
+ console.log(` - Claude Code: ${targetCounts.claudecode} rules`);
1191
1283
  console.log(` - Roo: ${targetCounts.roo} rules`);
1192
1284
  }
1193
1285
  console.log("\n\u{1F4E4} Generated files:");
@@ -1286,12 +1378,12 @@ async function watchCommand() {
1286
1378
 
1287
1379
  // src/cli/index.ts
1288
1380
  var program = new Command();
1289
- program.name("rulesync").description("Unified AI rules management CLI tool").version("0.28.0");
1381
+ program.name("rulesync").description("Unified AI rules management CLI tool").version("0.31.0");
1290
1382
  program.command("init").description("Initialize rulesync in current directory").action(initCommand);
1291
1383
  program.command("add <filename>").description("Add a new rule file").action(addCommand);
1292
1384
  program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
1293
- program.command("import").description("Import configurations from AI tools to rulesync format").option("--claude", "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("-v, --verbose", "Verbose output").action(importCommand);
1294
- program.command("generate").description("Generate configuration files for AI tools").option("--copilot", "Generate only for GitHub Copilot").option("--cursor", "Generate only for Cursor").option("--cline", "Generate only for Cline").option("--claude", "Generate only for Claude Code").option("--roo", "Generate only for Roo Code").option("--delete", "Delete all existing files in output directories before generating").option(
1385
+ program.command("import").description("Import configurations from AI tools to rulesync format").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("-v, --verbose", "Verbose output").action(importCommand);
1386
+ program.command("generate").description("Generate configuration files for AI tools").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("--delete", "Delete all existing files in output directories before generating").option(
1295
1387
  "-b, --base-dir <paths>",
1296
1388
  "Base directories to generate files (comma-separated for multiple paths)"
1297
1389
  ).option("-v, --verbose", "Verbose output").action(async (options) => {
@@ -1299,7 +1391,7 @@ program.command("generate").description("Generate configuration files for AI too
1299
1391
  if (options.copilot) tools.push("copilot");
1300
1392
  if (options.cursor) tools.push("cursor");
1301
1393
  if (options.cline) tools.push("cline");
1302
- if (options.claude) tools.push("claude");
1394
+ if (options.claudecode) tools.push("claudecode");
1303
1395
  if (options.roo) tools.push("roo");
1304
1396
  const generateOptions = {
1305
1397
  verbose: options.verbose,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rulesync",
3
- "version": "0.28.0",
3
+ "version": "0.31.0",
4
4
  "description": "Unified AI rules management CLI tool that generates configuration files for various AI development tools",
5
5
  "keywords": [
6
6
  "ai",
@@ -35,12 +35,14 @@
35
35
  "chokidar": "4.0.3",
36
36
  "commander": "14.0.0",
37
37
  "gray-matter": "4.0.3",
38
+ "js-yaml": "4.1.0",
38
39
  "marked": "15.0.12"
39
40
  },
40
41
  "devDependencies": {
41
42
  "@biomejs/biome": "2.0.0",
42
43
  "@secretlint/secretlint-rule-preset-recommend": "10.1.0",
43
44
  "@tsconfig/node24": "24.0.1",
45
+ "@types/js-yaml": "4.0.9",
44
46
  "@types/node": "24.0.3",
45
47
  "@typescript/native-preview": "7.0.0-dev.20250623.1",
46
48
  "@vitest/coverage-v8": "3.2.4",