From 4a46b891acb04f4b9e932837f12be2e7c40aef99 Mon Sep 17 00:00:00 2001 From: Masaaki Takeuchi Date: Wed, 25 Jun 2025 10:15:42 +0900 Subject: [PATCH] fix: add claudecode to valid targets in parser validation Previously, the claudecode parser would generate frontmatter with targets: ["claudecode"], but the validation logic only allowed ["copilot", "cursor", "cline", "claude", "roo", "*"], causing validation errors when importing from Claude Code. This commit: - Adds "claudecode" to the validTargets array in parser.ts - Adds comprehensive tests for claudecode target validation - Ensures both "claude" and "claudecode" are valid targets Fixes the issue where `rulesync validate` would fail with: "Invalid target 'claudecode' in .rulesync/claudecode__claude-main.md" --- src/core/parser.test.ts | 39 +++++++++++++++++++++++++++++++++++++++ src/core/parser.ts | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/core/parser.test.ts b/src/core/parser.test.ts index cdb25cba7..d7422304b 100644 --- a/src/core/parser.test.ts +++ b/src/core/parser.test.ts @@ -209,6 +209,45 @@ globs: ["**/*.ts"] await expect(parseRuleFile(filepath)).rejects.toThrow('Invalid "targets" field'); }); + + it("should accept claudecode as valid target", async () => { + const ruleContent = `--- +root: false +targets: ["claudecode"] +description: "Test rule for Claude Code" +globs: ["**/*.ts"] +--- + +# Claude Code Rule +`; + + const filepath = join(testDir, "claudecode-rule.md"); + writeFileSync(filepath, ruleContent); + + const rule = await parseRuleFile(filepath); + + expect(rule.frontmatter.targets).toEqual(["claudecode"]); + expect(rule.frontmatter.description).toBe("Test rule for Claude Code"); + }); + + it("should accept mixed targets including claudecode", async () => { + const ruleContent = `--- +root: false +targets: ["copilot", "claudecode", "cursor"] +description: "Test rule for multiple tools including Claude Code" +globs: ["**/*.ts"] +--- + +# Mixed Targets with Claude Code +`; + + const filepath = join(testDir, "mixed-claudecode-rule.md"); + writeFileSync(filepath, ruleContent); + + const rule = await parseRuleFile(filepath); + + expect(rule.frontmatter.targets).toEqual(["copilot", "claudecode", "cursor"]); + }); }); describe("parseRulesFromDirectory", () => { diff --git a/src/core/parser.ts b/src/core/parser.ts index 4533b4cb0..baec5c0e0 100644 --- a/src/core/parser.ts +++ b/src/core/parser.ts @@ -93,7 +93,7 @@ function validateFrontmatter(data: unknown, filepath: string): void { ); } - const validTargets = ["copilot", "cursor", "cline", "claude", "roo", "*"]; + const validTargets = ["copilot", "cursor", "cline", "claude", "claudecode", "roo", "*"]; for (const target of obj.targets) { if (typeof target !== "string" || !validTargets.includes(target)) { throw new Error(