skiller 0.7.6 → 0.7.7
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.md +22 -19
- package/dist/core/FileSystemUtils.js +4 -2
- package/dist/core/SkillsProcessor.js +20 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,12 +5,12 @@ A Claude-centric fork of [ruler](https://github.com/intellectronica/ruler) with
|
|
|
5
5
|
## 1. Skills as Source of Truth
|
|
6
6
|
|
|
7
7
|
- `.claude/skills/` is the committed source of truth for skills
|
|
8
|
-
- **Bidirectional sync** between `.mdc` and `SKILL.md
|
|
9
|
-
- Create `.claude/skills/foo.mdc` → auto-generates `.claude/skills/foo/SKILL.md`
|
|
10
|
-
- Create `.claude/skills/foo/SKILL.md` → auto-generates `.claude/skills/foo.mdc`
|
|
11
|
-
-
|
|
8
|
+
- **Bidirectional sync** between `.mdc` and `SKILL.md` (sibling pattern):
|
|
9
|
+
- Create `.claude/skills/foo/foo.mdc` → auto-generates `.claude/skills/foo/SKILL.md`
|
|
10
|
+
- Create `.claude/skills/foo/SKILL.md` → auto-generates `.claude/skills/foo/foo.mdc`
|
|
11
|
+
- Sync direction detected via `@reference` body pattern (SKILL.md with `@path` = .mdc is source)
|
|
12
12
|
- Edit either file, the other stays in sync on next `skiller apply`
|
|
13
|
-
-
|
|
13
|
+
- `.claude/rules/` contents are migrated to `.claude/skills/` and rules directory is deleted
|
|
14
14
|
|
|
15
15
|
## 2. CLAUDE.md @filename References
|
|
16
16
|
|
|
@@ -84,7 +84,7 @@ Skiller solves this by providing a **single source of truth** for all your AI ag
|
|
|
84
84
|
| AGENTS.md | `AGENTS.md` | (pseudo-agent ensuring root `AGENTS.md` exists) |
|
|
85
85
|
| GitHub Copilot | `AGENTS.md` | `.vscode/mcp.json` |
|
|
86
86
|
| Claude Code | `CLAUDE.md` (@filename references) | `.mcp.json` |
|
|
87
|
-
| OpenAI Codex CLI | `AGENTS.md` | `.codex/config.toml`
|
|
87
|
+
| OpenAI Codex CLI | `AGENTS.md` | `.codex/config.toml` |
|
|
88
88
|
| Jules | `AGENTS.md` | - |
|
|
89
89
|
| Cursor | `AGENTS.md` | `.cursor/mcp.json` |
|
|
90
90
|
| Windsurf | `AGENTS.md` | `.windsurf/mcp_config.json` |
|
|
@@ -567,11 +567,12 @@ Skills can be organized flat or nested:
|
|
|
567
567
|
|
|
568
568
|
```
|
|
569
569
|
.claude/skills/
|
|
570
|
-
├── my-skill.mdc # Standalone skill file (auto-syncs to folder)
|
|
571
570
|
├── my-skill/
|
|
572
|
-
│
|
|
571
|
+
│ ├── my-skill.mdc # Skill content (body)
|
|
572
|
+
│ └── SKILL.md # @reference to my-skill.mdc (frontmatter here)
|
|
573
573
|
├── another-skill/
|
|
574
|
-
│ ├──
|
|
574
|
+
│ ├── another-skill.mdc # Generated from SKILL.md body
|
|
575
|
+
│ ├── SKILL.md # Manually created skill (now @reference)
|
|
575
576
|
│ ├── helper.py # Optional: additional resources (scripts)
|
|
576
577
|
│ └── reference.md # Optional: additional resources (docs)
|
|
577
578
|
```
|
|
@@ -587,25 +588,24 @@ Skiller provides bidirectional sync between `.mdc` files and `SKILL.md` folders:
|
|
|
587
588
|
|
|
588
589
|
| Scenario | Sync Direction |
|
|
589
590
|
|----------|---------------|
|
|
590
|
-
| `.mdc` exists, no `SKILL.md` | → Generate `SKILL.md` with `
|
|
591
|
-
| `SKILL.md`
|
|
592
|
-
| `SKILL.md`
|
|
591
|
+
| `.mdc` exists, no `SKILL.md` | → Generate `SKILL.md` with `@reference` to .mdc |
|
|
592
|
+
| `SKILL.md` body is `@reference` | .mdc is source of truth (frontmatter in SKILL.md) |
|
|
593
|
+
| `SKILL.md` has full content | → Generate .mdc from body, update SKILL.md to `@reference` |
|
|
593
594
|
|
|
594
|
-
The `
|
|
595
|
+
The `@reference` body pattern indicates that the `.mdc` file contains the skill content:
|
|
595
596
|
|
|
596
597
|
```yaml
|
|
597
598
|
---
|
|
598
599
|
name: my-skill
|
|
599
600
|
description: My custom skill
|
|
600
|
-
synced: true
|
|
601
601
|
---
|
|
602
602
|
|
|
603
|
-
|
|
603
|
+
@.claude/skills/my-skill/my-skill.mdc
|
|
604
604
|
```
|
|
605
605
|
|
|
606
|
-
###
|
|
606
|
+
### Rules Migration
|
|
607
607
|
|
|
608
|
-
|
|
608
|
+
Content from `.claude/rules/` is automatically migrated to `.claude/skills/` during `skiller apply`, then the rules directory is deleted:
|
|
609
609
|
|
|
610
610
|
```
|
|
611
611
|
.claude/rules/docx/
|
|
@@ -614,13 +614,16 @@ Skill folders (directories containing `SKILL.md`) in `.claude/rules/` are automa
|
|
|
614
614
|
└── templates/ # Subdirectory
|
|
615
615
|
└── default.docx # Template file
|
|
616
616
|
|
|
617
|
-
→
|
|
617
|
+
→ Migrated to:
|
|
618
618
|
|
|
619
619
|
.claude/skills/docx/
|
|
620
|
-
├──
|
|
620
|
+
├── docx.mdc # Generated from SKILL.md body
|
|
621
|
+
├── SKILL.md # Updated to @reference
|
|
621
622
|
├── script.sh # Copied automatically
|
|
622
623
|
└── templates/ # Copied automatically
|
|
623
624
|
└── default.docx # Copied automatically
|
|
625
|
+
|
|
626
|
+
.claude/rules/ → Deleted after migration
|
|
624
627
|
```
|
|
625
628
|
|
|
626
629
|
### Configuration
|
|
@@ -236,8 +236,10 @@ async function readMarkdownFiles(skillerDir, options) {
|
|
|
236
236
|
cursorFiles.push(file);
|
|
237
237
|
continue;
|
|
238
238
|
}
|
|
239
|
-
// Check if file is in rules/ folder and is .mdc
|
|
240
|
-
if (normalizedPath.startsWith('rules/')
|
|
239
|
+
// Check if file is in rules/ or skills/ folder and is .mdc
|
|
240
|
+
if ((normalizedPath.startsWith('rules/') ||
|
|
241
|
+
normalizedPath.startsWith('skills/')) &&
|
|
242
|
+
file.path.endsWith('.mdc')) {
|
|
241
243
|
// Parse frontmatter
|
|
242
244
|
const parsed = (0, FrontmatterParser_1.parseFrontmatter)(file.content);
|
|
243
245
|
// Only include if alwaysApply is true
|
|
@@ -237,8 +237,26 @@ ${yaml.dump(skillFrontmatter || { name: skillName }, { lineWidth: -1, noRefs: tr
|
|
|
237
237
|
else {
|
|
238
238
|
referencedPath = path.resolve(skillFolderPath, refCheck.referencePath);
|
|
239
239
|
}
|
|
240
|
+
// One-time migration: for old @.claude/rules/ references, look at the
|
|
241
|
+
// already-migrated skills location. After migration, SKILL.md will have
|
|
242
|
+
// @.claude/skills/ references, so this code path won't be hit again.
|
|
243
|
+
let actualPath = referencedPath;
|
|
244
|
+
if (refCheck.referencePath?.includes('/rules/')) {
|
|
245
|
+
const refFileName = path.basename(refCheck.referencePath);
|
|
246
|
+
const refBaseName = path.basename(refFileName, '.mdc');
|
|
247
|
+
actualPath = path.join(skillsDir, refBaseName, refFileName);
|
|
248
|
+
}
|
|
249
|
+
let referencedContent = null;
|
|
240
250
|
try {
|
|
241
|
-
|
|
251
|
+
referencedContent = await fs.readFile(actualPath, 'utf8');
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// File not found
|
|
255
|
+
}
|
|
256
|
+
if (referencedContent === null) {
|
|
257
|
+
warnings.push(`Cannot migrate ${skillName}: referenced file not found at ${actualPath}`);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
242
260
|
// Parse the referenced file for frontmatter
|
|
243
261
|
const { frontmatter: refFrontmatter, body: refBody } = (0, FrontmatterParser_1.parseFrontmatter)(referencedContent);
|
|
244
262
|
// Create sibling .mdc - only keep frontmatter for alwaysApply rules
|
|
@@ -281,14 +299,10 @@ ${yaml.dump(newFrontmatter, { lineWidth: -1, noRefs: true }).trim()}
|
|
|
281
299
|
else {
|
|
282
300
|
await fs.writeFile(siblingMdcPath, mdcContent, 'utf8');
|
|
283
301
|
await fs.writeFile(skillMdPath, newSkillMd, 'utf8');
|
|
284
|
-
(0, constants_1.logVerboseInfo)(`Migrated ${skillName} from ${
|
|
302
|
+
(0, constants_1.logVerboseInfo)(`Migrated ${skillName} from ${actualPath} to sibling pattern`, verbose, dryRun);
|
|
285
303
|
}
|
|
286
304
|
synced.push(skillName);
|
|
287
305
|
}
|
|
288
|
-
catch {
|
|
289
|
-
// Referenced file doesn't exist or can't be read
|
|
290
|
-
warnings.push(`Cannot migrate ${skillName}: referenced file ${refCheck.referencePath} not found or unreadable`);
|
|
291
|
-
}
|
|
292
306
|
}
|
|
293
307
|
}
|
|
294
308
|
else {
|