@intellectronica/ruler 0.3.37 → 0.3.38
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 +2 -1
- package/dist/agents/WindsurfAgent.js +3 -0
- package/dist/constants.js +2 -1
- package/dist/core/SkillsProcessor.js +73 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ Ruler solves this by providing a **single source of truth** for all your AI agen
|
|
|
63
63
|
| Pi Coding Agent | `AGENTS.md` | - | `.pi/skills/` |
|
|
64
64
|
| Jules | `AGENTS.md` | - | - |
|
|
65
65
|
| Cursor | `AGENTS.md` | `.cursor/mcp.json` | `.cursor/skills/` |
|
|
66
|
-
| Windsurf | `AGENTS.md` | `.windsurf/mcp_config.json` |
|
|
66
|
+
| Windsurf | `AGENTS.md` | `.windsurf/mcp_config.json` | `.windsurf/skills/` |
|
|
67
67
|
| Cline | `.clinerules` | - | - |
|
|
68
68
|
| Crush | `CRUSH.md` | `.crush.json` | - |
|
|
69
69
|
| Amp | `AGENTS.md` | - | `.agents/skills/` |
|
|
@@ -596,6 +596,7 @@ Skills are specialized knowledge packages that extend AI agent capabilities with
|
|
|
596
596
|
- **Gemini CLI**: `.gemini/skills/`
|
|
597
597
|
- **Junie**: `.junie/skills/`
|
|
598
598
|
- **Cursor**: `.cursor/skills/`
|
|
599
|
+
- **Windsurf**: `.windsurf/skills/`
|
|
599
600
|
|
|
600
601
|
### Skills Directory Structure
|
|
601
602
|
|
package/dist/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SKILL_MD_FILENAME = exports.ANTIGRAVITY_SKILLS_PATH = exports.FACTORY_SKILLS_PATH = exports.CURSOR_SKILLS_PATH = exports.JUNIE_SKILLS_PATH = exports.GEMINI_SKILLS_PATH = exports.ROO_SKILLS_PATH = exports.VIBE_SKILLS_PATH = exports.GOOSE_SKILLS_PATH = exports.PI_SKILLS_PATH = exports.OPENCODE_SKILLS_PATH = exports.CODEX_SKILLS_PATH = exports.CLAUDE_SKILLS_PATH = exports.RULER_SKILLS_PATH = exports.SKILLS_DIR = exports.DEFAULT_RULES_FILENAME = exports.ERROR_PREFIX = void 0;
|
|
3
|
+
exports.SKILL_MD_FILENAME = exports.ANTIGRAVITY_SKILLS_PATH = exports.FACTORY_SKILLS_PATH = exports.WINDSURF_SKILLS_PATH = exports.CURSOR_SKILLS_PATH = exports.JUNIE_SKILLS_PATH = exports.GEMINI_SKILLS_PATH = exports.ROO_SKILLS_PATH = exports.VIBE_SKILLS_PATH = exports.GOOSE_SKILLS_PATH = exports.PI_SKILLS_PATH = exports.OPENCODE_SKILLS_PATH = exports.CODEX_SKILLS_PATH = exports.CLAUDE_SKILLS_PATH = exports.RULER_SKILLS_PATH = exports.SKILLS_DIR = exports.DEFAULT_RULES_FILENAME = exports.ERROR_PREFIX = void 0;
|
|
4
4
|
exports.actionPrefix = actionPrefix;
|
|
5
5
|
exports.createRulerError = createRulerError;
|
|
6
6
|
exports.logVerbose = logVerbose;
|
|
@@ -62,6 +62,7 @@ exports.ROO_SKILLS_PATH = '.roo/skills';
|
|
|
62
62
|
exports.GEMINI_SKILLS_PATH = '.gemini/skills';
|
|
63
63
|
exports.JUNIE_SKILLS_PATH = '.junie/skills';
|
|
64
64
|
exports.CURSOR_SKILLS_PATH = '.cursor/skills';
|
|
65
|
+
exports.WINDSURF_SKILLS_PATH = '.windsurf/skills';
|
|
65
66
|
exports.FACTORY_SKILLS_PATH = '.factory/skills';
|
|
66
67
|
exports.ANTIGRAVITY_SKILLS_PATH = '.agent/skills';
|
|
67
68
|
exports.SKILL_MD_FILENAME = 'SKILL.md';
|
|
@@ -46,6 +46,7 @@ exports.propagateSkillsForRoo = propagateSkillsForRoo;
|
|
|
46
46
|
exports.propagateSkillsForGemini = propagateSkillsForGemini;
|
|
47
47
|
exports.propagateSkillsForJunie = propagateSkillsForJunie;
|
|
48
48
|
exports.propagateSkillsForCursor = propagateSkillsForCursor;
|
|
49
|
+
exports.propagateSkillsForWindsurf = propagateSkillsForWindsurf;
|
|
49
50
|
exports.propagateSkillsForFactory = propagateSkillsForFactory;
|
|
50
51
|
exports.propagateSkillsForAntigravity = propagateSkillsForAntigravity;
|
|
51
52
|
const path = __importStar(require("path"));
|
|
@@ -83,7 +84,7 @@ async function getSkillsGitignorePaths(projectRoot, agents) {
|
|
|
83
84
|
return [];
|
|
84
85
|
}
|
|
85
86
|
// Import here to avoid circular dependency
|
|
86
|
-
const { CLAUDE_SKILLS_PATH, CODEX_SKILLS_PATH, OPENCODE_SKILLS_PATH, PI_SKILLS_PATH, GOOSE_SKILLS_PATH, VIBE_SKILLS_PATH, ROO_SKILLS_PATH, GEMINI_SKILLS_PATH, JUNIE_SKILLS_PATH, CURSOR_SKILLS_PATH, FACTORY_SKILLS_PATH, ANTIGRAVITY_SKILLS_PATH, } = await Promise.resolve().then(() => __importStar(require('../constants')));
|
|
87
|
+
const { CLAUDE_SKILLS_PATH, CODEX_SKILLS_PATH, OPENCODE_SKILLS_PATH, PI_SKILLS_PATH, GOOSE_SKILLS_PATH, VIBE_SKILLS_PATH, ROO_SKILLS_PATH, GEMINI_SKILLS_PATH, JUNIE_SKILLS_PATH, CURSOR_SKILLS_PATH, WINDSURF_SKILLS_PATH, FACTORY_SKILLS_PATH, ANTIGRAVITY_SKILLS_PATH, } = await Promise.resolve().then(() => __importStar(require('../constants')));
|
|
87
88
|
const selectedTargets = getSelectedSkillTargets(agents);
|
|
88
89
|
const targetPaths = {
|
|
89
90
|
claude: CLAUDE_SKILLS_PATH,
|
|
@@ -96,6 +97,7 @@ async function getSkillsGitignorePaths(projectRoot, agents) {
|
|
|
96
97
|
gemini: GEMINI_SKILLS_PATH,
|
|
97
98
|
junie: JUNIE_SKILLS_PATH,
|
|
98
99
|
cursor: CURSOR_SKILLS_PATH,
|
|
100
|
+
windsurf: WINDSURF_SKILLS_PATH,
|
|
99
101
|
factory: FACTORY_SKILLS_PATH,
|
|
100
102
|
antigravity: ANTIGRAVITY_SKILLS_PATH,
|
|
101
103
|
};
|
|
@@ -130,6 +132,7 @@ const SKILL_TARGET_TO_IDENTIFIERS = new Map([
|
|
|
130
132
|
['gemini', ['gemini-cli']],
|
|
131
133
|
['junie', ['junie']],
|
|
132
134
|
['cursor', ['cursor']],
|
|
135
|
+
['windsurf', ['windsurf']],
|
|
133
136
|
['factory', ['factory']],
|
|
134
137
|
['antigravity', ['antigravity']],
|
|
135
138
|
]);
|
|
@@ -160,6 +163,7 @@ async function cleanupSkillsDirectories(projectRoot, dryRun, verbose) {
|
|
|
160
163
|
const geminiSkillsPath = path.join(projectRoot, constants_1.GEMINI_SKILLS_PATH);
|
|
161
164
|
const junieSkillsPath = path.join(projectRoot, constants_1.JUNIE_SKILLS_PATH);
|
|
162
165
|
const cursorSkillsPath = path.join(projectRoot, constants_1.CURSOR_SKILLS_PATH);
|
|
166
|
+
const windsurfSkillsPath = path.join(projectRoot, constants_1.WINDSURF_SKILLS_PATH);
|
|
163
167
|
const factorySkillsPath = path.join(projectRoot, constants_1.FACTORY_SKILLS_PATH);
|
|
164
168
|
const antigravitySkillsPath = path.join(projectRoot, constants_1.ANTIGRAVITY_SKILLS_PATH);
|
|
165
169
|
// Clean up .claude/skills
|
|
@@ -302,6 +306,20 @@ async function cleanupSkillsDirectories(projectRoot, dryRun, verbose) {
|
|
|
302
306
|
catch {
|
|
303
307
|
// Directory doesn't exist, nothing to clean
|
|
304
308
|
}
|
|
309
|
+
// Clean up .windsurf/skills
|
|
310
|
+
try {
|
|
311
|
+
await fs.access(windsurfSkillsPath);
|
|
312
|
+
if (dryRun) {
|
|
313
|
+
(0, constants_1.logVerboseInfo)(`DRY RUN: Would remove ${constants_1.WINDSURF_SKILLS_PATH}`, verbose, dryRun);
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
await fs.rm(windsurfSkillsPath, { recursive: true, force: true });
|
|
317
|
+
(0, constants_1.logVerboseInfo)(`Removed ${constants_1.WINDSURF_SKILLS_PATH} (skills disabled)`, verbose, dryRun);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
// Directory doesn't exist, nothing to clean
|
|
322
|
+
}
|
|
305
323
|
// Clean up .factory/skills
|
|
306
324
|
try {
|
|
307
325
|
await fs.access(factorySkillsPath);
|
|
@@ -421,6 +439,10 @@ async function propagateSkills(projectRoot, agents, skillsEnabled, verbose, dryR
|
|
|
421
439
|
(0, constants_1.logVerboseInfo)(`Copying skills to ${constants_1.CURSOR_SKILLS_PATH} for Cursor`, verbose, dryRun);
|
|
422
440
|
await propagateSkillsForCursor(projectRoot, { dryRun });
|
|
423
441
|
}
|
|
442
|
+
if (selectedTargets.has('windsurf')) {
|
|
443
|
+
(0, constants_1.logVerboseInfo)(`Copying skills to ${constants_1.WINDSURF_SKILLS_PATH} for Windsurf`, verbose, dryRun);
|
|
444
|
+
await propagateSkillsForWindsurf(projectRoot, { dryRun });
|
|
445
|
+
}
|
|
424
446
|
if (selectedTargets.has('factory')) {
|
|
425
447
|
(0, constants_1.logVerboseInfo)(`Copying skills to ${constants_1.FACTORY_SKILLS_PATH} for Factory Droid`, verbose, dryRun);
|
|
426
448
|
await propagateSkillsForFactory(projectRoot, { dryRun });
|
|
@@ -922,6 +944,56 @@ async function propagateSkillsForCursor(projectRoot, options) {
|
|
|
922
944
|
}
|
|
923
945
|
return [];
|
|
924
946
|
}
|
|
947
|
+
/**
|
|
948
|
+
* Propagates skills for Windsurf by copying .ruler/skills to .windsurf/skills.
|
|
949
|
+
* Uses atomic replace to ensure safe overwriting of existing skills.
|
|
950
|
+
* Returns dry-run steps if dryRun is true, otherwise returns empty array.
|
|
951
|
+
*/
|
|
952
|
+
async function propagateSkillsForWindsurf(projectRoot, options) {
|
|
953
|
+
const skillsDir = path.join(projectRoot, constants_1.RULER_SKILLS_PATH);
|
|
954
|
+
const windsurfSkillsPath = path.join(projectRoot, constants_1.WINDSURF_SKILLS_PATH);
|
|
955
|
+
const windsurfDir = path.dirname(windsurfSkillsPath);
|
|
956
|
+
// Check if source skills directory exists
|
|
957
|
+
try {
|
|
958
|
+
await fs.access(skillsDir);
|
|
959
|
+
}
|
|
960
|
+
catch {
|
|
961
|
+
// No skills directory - return empty
|
|
962
|
+
return [];
|
|
963
|
+
}
|
|
964
|
+
if (options.dryRun) {
|
|
965
|
+
return [`Copy skills from ${constants_1.RULER_SKILLS_PATH} to ${constants_1.WINDSURF_SKILLS_PATH}`];
|
|
966
|
+
}
|
|
967
|
+
// Ensure .windsurf directory exists
|
|
968
|
+
await fs.mkdir(windsurfDir, { recursive: true });
|
|
969
|
+
// Use atomic replace: copy to temp, then rename
|
|
970
|
+
const tempDir = path.join(windsurfDir, `skills.tmp-${Date.now()}`);
|
|
971
|
+
try {
|
|
972
|
+
// Copy to temp directory
|
|
973
|
+
await (0, SkillsUtils_1.copySkillsDirectory)(skillsDir, tempDir);
|
|
974
|
+
// Atomically replace the target
|
|
975
|
+
// First, remove existing target if it exists
|
|
976
|
+
try {
|
|
977
|
+
await fs.rm(windsurfSkillsPath, { recursive: true, force: true });
|
|
978
|
+
}
|
|
979
|
+
catch {
|
|
980
|
+
// Target didn't exist, that's fine
|
|
981
|
+
}
|
|
982
|
+
// Rename temp to target
|
|
983
|
+
await fs.rename(tempDir, windsurfSkillsPath);
|
|
984
|
+
}
|
|
985
|
+
catch (error) {
|
|
986
|
+
// Clean up temp directory on error
|
|
987
|
+
try {
|
|
988
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
989
|
+
}
|
|
990
|
+
catch {
|
|
991
|
+
// Ignore cleanup errors
|
|
992
|
+
}
|
|
993
|
+
throw error;
|
|
994
|
+
}
|
|
995
|
+
return [];
|
|
996
|
+
}
|
|
925
997
|
/**
|
|
926
998
|
* Propagates skills for Factory Droid by copying .ruler/skills to .factory/skills.
|
|
927
999
|
* Uses atomic replace to ensure safe overwriting of existing skills.
|