Skip to content

Commit 332f934

Browse files
clevin95claude
andcommitted
Output skills directly to .claude/skills/ (not nested under .generated/)
Claude Code only discovers skills one level deep under .claude/skills/, so the .generated/ subdirectory was preventing skills from loading. Skills now go directly to .claude/skills/generated_<category>_<skill>/SKILL.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d9aa970 commit 332f934

4 files changed

Lines changed: 11 additions & 19 deletions

File tree

sync_ai_rules/generators/skills_generator.py

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python3
22
"""
33
Skills Generator - generates Claude Code skills from .cursor/rules/.
4-
Each rule becomes a separate SKILL.md file in .claude/skills/.generated/,
4+
Each rule becomes a separate SKILL.md file in .claude/skills/,
55
with a flat name encoding the full path: generated_<category>_<skill-name>.
66
"""
77

@@ -14,7 +14,7 @@
1414
from sync_ai_rules.core.generator_interface import OutputGenerator
1515
from sync_ai_rules.core.rule_metadata import RuleMetadata
1616

17-
_SKILLS_DIR = ".claude/skills/.generated"
17+
_SKILLS_DIR = ".claude/skills"
1818
_SOURCE_DIR = ".cursor/rules"
1919
_YAML_UNSAFE = re.compile(r"[:\#\[\]\{\}&*!|>'\"%@`]")
2020

@@ -43,28 +43,20 @@ def is_multi_file(self) -> bool:
4343
def generate_files(
4444
self, rules: Dict[str, List[RuleMetadata]], project_root: str
4545
) -> None:
46-
"""Generate skill files mirroring the .cursor/rules/ folder structure."""
46+
"""Generate skill files as direct children of .claude/skills/."""
4747
skills_root = os.path.join(project_root, _SKILLS_DIR)
4848

49-
# Clean .generated directory on each run
50-
if os.path.exists(skills_root):
51-
shutil.rmtree(skills_root)
52-
53-
# Also remove any stale generated_* dirs that may exist directly in .claude/skills/
54-
# (e.g. from a previous migration or manual copy)
55-
skills_parent = os.path.dirname(skills_root)
56-
if os.path.isdir(skills_parent):
57-
for entry in os.listdir(skills_parent):
49+
# Remove any existing generated_* dirs before regenerating
50+
if os.path.isdir(skills_root):
51+
for entry in os.listdir(skills_root):
5852
if entry.startswith("generated_"):
59-
stale = os.path.join(skills_parent, entry)
60-
if os.path.isdir(stale):
61-
shutil.rmtree(stale)
53+
shutil.rmtree(os.path.join(skills_root, entry))
6254

6355
for category_rules in rules.values():
6456
for rule in category_rules:
65-
# Flatten full path into skill name:
66-
# .cursor/rules/arch/my-rule.mdc → .generated/generated_arch_my-rule/SKILL.md
67-
# .cursor/rules/my-rule.mdc → .generated/generated_my-rule/SKILL.md
57+
# Flatten full path into a single skill dir name:
58+
# .cursor/rules/arch/my-rule.mdc → .claude/skills/generated_arch_my-rule/SKILL.md
59+
# .cursor/rules/my-rule.mdc → .claude/skills/generated_my-rule/SKILL.md
6860
rel_path = _strip_source_prefix(rule.relative_path)
6961
path_parts = rel_path.replace(os.sep, "/").split("/")
7062
path_parts[-1] = os.path.splitext(path_parts[-1])[0]
@@ -77,7 +69,7 @@ def generate_files(
7769
os.makedirs(skill_dir, exist_ok=True)
7870
with open(skill_file, "w", encoding="utf-8") as f:
7971
f.write(content)
80-
print(f" ✓ Created skill: {os.path.relpath(skill_dir, skills_root)}")
72+
print(f" ✓ Created skill: {skill_name}")
8173
except OSError as e:
8274
logger.warning("Failed to write skill %s: %s", skill_name, e)
8375
print(f" ✗ Failed to create skill: {skill_name}")

test/after/.claude/skills/.generated/generated_architecture_architecture-rule/SKILL.md renamed to test/after/.claude/skills/generated_architecture_architecture-rule/SKILL.md

File renamed without changes.

test/after/.claude/skills/.generated/generated_rule/SKILL.md renamed to test/after/.claude/skills/generated_rule/SKILL.md

File renamed without changes.

test/after/.claude/skills/.generated/generated_testing_testing-rule/SKILL.md renamed to test/after/.claude/skills/generated_testing_testing-rule/SKILL.md

File renamed without changes.

0 commit comments

Comments
 (0)