@intellectronica/ruler 0.3.36 → 0.3.37
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 +13 -10
- package/dist/agents/JunieAgent.js +3 -0
- package/dist/constants.js +2 -1
- package/dist/core/SkillsProcessor.js +64 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,7 +73,7 @@ Ruler solves this by providing a **single source of truth** for all your AI agen
|
|
|
73
73
|
| Firebase Studio | `.idx/airules.md` | `.idx/mcp.json` | - |
|
|
74
74
|
| Open Hands | `.openhands/microagents/repo.md` | `config.toml` | - |
|
|
75
75
|
| Gemini CLI | `AGENTS.md` | `.gemini/settings.json` | `.gemini/skills/` |
|
|
76
|
-
| Junie | `.junie/guidelines.md` | `.junie/mcp/mcp.json` |
|
|
76
|
+
| Junie | `.junie/guidelines.md` | `.junie/mcp/mcp.json` | `.junie/skills/` |
|
|
77
77
|
| AugmentCode | `.augment/rules/ruler_augment_instructions.md` | - | - |
|
|
78
78
|
| Kilo Code | `AGENTS.md` | `.kilocode/mcp.json` | `.claude/skills/` |
|
|
79
79
|
| OpenCode | `AGENTS.md` | `opencode.json` | `.opencode/skills/` |
|
|
@@ -325,15 +325,15 @@ ruler revert [options]
|
|
|
325
325
|
|
|
326
326
|
### Options
|
|
327
327
|
|
|
328
|
-
| Option | Description
|
|
329
|
-
| ------------------------------ |
|
|
330
|
-
| `--project-root <path>` | Path to your project's root (default: current directory)
|
|
328
|
+
| Option | Description |
|
|
329
|
+
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
330
|
+
| `--project-root <path>` | Path to your project's root (default: current directory) |
|
|
331
331
|
| `--agents <agent1,agent2,...>` | Comma-separated list of agent names to revert (agentsmd, aider, amazonqcli, amp, antigravity, augmentcode, claude, cline, codex, copilot, crush, cursor, factory, firebase, firebender, gemini-cli, goose, jetbrains-ai, jules, junie, kilocode, kiro, mistral, opencode, openhands, pi, qwen, roo, trae, warp, windsurf, zed) |
|
|
332
|
-
| `--config <path>` | Path to a custom `ruler.toml` configuration file
|
|
333
|
-
| `--keep-backups` | Keep backup files (.bak) after restoration (default: false)
|
|
334
|
-
| `--dry-run` | Preview changes without actually reverting files
|
|
335
|
-
| `--verbose` / `-v` | Display detailed output during execution
|
|
336
|
-
| `--local-only` | Only search for local .ruler directories, ignore global config
|
|
332
|
+
| `--config <path>` | Path to a custom `ruler.toml` configuration file |
|
|
333
|
+
| `--keep-backups` | Keep backup files (.bak) after restoration (default: false) |
|
|
334
|
+
| `--dry-run` | Preview changes without actually reverting files |
|
|
335
|
+
| `--verbose` / `-v` | Display detailed output during execution |
|
|
336
|
+
| `--local-only` | Only search for local .ruler directories, ignore global config |
|
|
337
337
|
|
|
338
338
|
### Common Examples
|
|
339
339
|
|
|
@@ -594,6 +594,7 @@ Skills are specialized knowledge packages that extend AI agent capabilities with
|
|
|
594
594
|
- **Mistral Vibe**: `.vibe/skills/`
|
|
595
595
|
- **Roo Code**: `.roo/skills/`
|
|
596
596
|
- **Gemini CLI**: `.gemini/skills/`
|
|
597
|
+
- **Junie**: `.junie/skills/`
|
|
597
598
|
- **Cursor**: `.cursor/skills/`
|
|
598
599
|
|
|
599
600
|
### Skills Directory Structure
|
|
@@ -659,13 +660,14 @@ When skills support is enabled and gitignore integration is active, Ruler automa
|
|
|
659
660
|
- `.vibe/skills/` (for Mistral Vibe)
|
|
660
661
|
- `.roo/skills/` (for Roo Code)
|
|
661
662
|
- `.gemini/skills/` (for Gemini CLI)
|
|
663
|
+
- `.junie/skills/` (for Junie)
|
|
662
664
|
- `.cursor/skills/` (for Cursor)
|
|
663
665
|
|
|
664
666
|
to your `.gitignore` file within the managed Ruler block.
|
|
665
667
|
|
|
666
668
|
### Requirements
|
|
667
669
|
|
|
668
|
-
- **For agents with native skills support** (Claude Code, GitHub Copilot, Kilo Code, OpenAI Codex CLI, OpenCode, Pi Coding Agent, Goose, Amp, Antigravity, Factory Droid, Mistral Vibe, Roo Code, Gemini CLI, Cursor): No additional requirements.
|
|
670
|
+
- **For agents with native skills support** (Claude Code, GitHub Copilot, Kilo Code, OpenAI Codex CLI, OpenCode, Pi Coding Agent, Goose, Amp, Antigravity, Factory Droid, Mistral Vibe, Roo Code, Gemini CLI, Junie, Cursor): No additional requirements.
|
|
669
671
|
|
|
670
672
|
### Validation
|
|
671
673
|
|
|
@@ -718,6 +720,7 @@ ruler apply
|
|
|
718
720
|
# - Mistral Vibe: .vibe/skills/my-skill/
|
|
719
721
|
# - Roo Code: .roo/skills/my-skill/
|
|
720
722
|
# - Gemini CLI: .gemini/skills/my-skill/
|
|
723
|
+
# - Junie: .junie/skills/my-skill/
|
|
721
724
|
# - Cursor: .cursor/skills/my-skill/
|
|
722
725
|
```
|
|
723
726
|
|
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.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.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;
|
|
@@ -60,6 +60,7 @@ exports.GOOSE_SKILLS_PATH = '.agents/skills';
|
|
|
60
60
|
exports.VIBE_SKILLS_PATH = '.vibe/skills';
|
|
61
61
|
exports.ROO_SKILLS_PATH = '.roo/skills';
|
|
62
62
|
exports.GEMINI_SKILLS_PATH = '.gemini/skills';
|
|
63
|
+
exports.JUNIE_SKILLS_PATH = '.junie/skills';
|
|
63
64
|
exports.CURSOR_SKILLS_PATH = '.cursor/skills';
|
|
64
65
|
exports.FACTORY_SKILLS_PATH = '.factory/skills';
|
|
65
66
|
exports.ANTIGRAVITY_SKILLS_PATH = '.agent/skills';
|
|
@@ -44,6 +44,7 @@ exports.propagateSkillsForGoose = propagateSkillsForGoose;
|
|
|
44
44
|
exports.propagateSkillsForVibe = propagateSkillsForVibe;
|
|
45
45
|
exports.propagateSkillsForRoo = propagateSkillsForRoo;
|
|
46
46
|
exports.propagateSkillsForGemini = propagateSkillsForGemini;
|
|
47
|
+
exports.propagateSkillsForJunie = propagateSkillsForJunie;
|
|
47
48
|
exports.propagateSkillsForCursor = propagateSkillsForCursor;
|
|
48
49
|
exports.propagateSkillsForFactory = propagateSkillsForFactory;
|
|
49
50
|
exports.propagateSkillsForAntigravity = propagateSkillsForAntigravity;
|
|
@@ -82,7 +83,7 @@ async function getSkillsGitignorePaths(projectRoot, agents) {
|
|
|
82
83
|
return [];
|
|
83
84
|
}
|
|
84
85
|
// Import here to avoid circular dependency
|
|
85
|
-
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, CURSOR_SKILLS_PATH, FACTORY_SKILLS_PATH, ANTIGRAVITY_SKILLS_PATH, } = await Promise.resolve().then(() => __importStar(require('../constants')));
|
|
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')));
|
|
86
87
|
const selectedTargets = getSelectedSkillTargets(agents);
|
|
87
88
|
const targetPaths = {
|
|
88
89
|
claude: CLAUDE_SKILLS_PATH,
|
|
@@ -93,6 +94,7 @@ async function getSkillsGitignorePaths(projectRoot, agents) {
|
|
|
93
94
|
vibe: VIBE_SKILLS_PATH,
|
|
94
95
|
roo: ROO_SKILLS_PATH,
|
|
95
96
|
gemini: GEMINI_SKILLS_PATH,
|
|
97
|
+
junie: JUNIE_SKILLS_PATH,
|
|
96
98
|
cursor: CURSOR_SKILLS_PATH,
|
|
97
99
|
factory: FACTORY_SKILLS_PATH,
|
|
98
100
|
antigravity: ANTIGRAVITY_SKILLS_PATH,
|
|
@@ -126,6 +128,7 @@ const SKILL_TARGET_TO_IDENTIFIERS = new Map([
|
|
|
126
128
|
['vibe', ['mistral']],
|
|
127
129
|
['roo', ['roo']],
|
|
128
130
|
['gemini', ['gemini-cli']],
|
|
131
|
+
['junie', ['junie']],
|
|
129
132
|
['cursor', ['cursor']],
|
|
130
133
|
['factory', ['factory']],
|
|
131
134
|
['antigravity', ['antigravity']],
|
|
@@ -155,6 +158,7 @@ async function cleanupSkillsDirectories(projectRoot, dryRun, verbose) {
|
|
|
155
158
|
const vibeSkillsPath = path.join(projectRoot, constants_1.VIBE_SKILLS_PATH);
|
|
156
159
|
const rooSkillsPath = path.join(projectRoot, constants_1.ROO_SKILLS_PATH);
|
|
157
160
|
const geminiSkillsPath = path.join(projectRoot, constants_1.GEMINI_SKILLS_PATH);
|
|
161
|
+
const junieSkillsPath = path.join(projectRoot, constants_1.JUNIE_SKILLS_PATH);
|
|
158
162
|
const cursorSkillsPath = path.join(projectRoot, constants_1.CURSOR_SKILLS_PATH);
|
|
159
163
|
const factorySkillsPath = path.join(projectRoot, constants_1.FACTORY_SKILLS_PATH);
|
|
160
164
|
const antigravitySkillsPath = path.join(projectRoot, constants_1.ANTIGRAVITY_SKILLS_PATH);
|
|
@@ -270,6 +274,20 @@ async function cleanupSkillsDirectories(projectRoot, dryRun, verbose) {
|
|
|
270
274
|
catch {
|
|
271
275
|
// Directory doesn't exist, nothing to clean
|
|
272
276
|
}
|
|
277
|
+
// Clean up .junie/skills
|
|
278
|
+
try {
|
|
279
|
+
await fs.access(junieSkillsPath);
|
|
280
|
+
if (dryRun) {
|
|
281
|
+
(0, constants_1.logVerboseInfo)(`DRY RUN: Would remove ${constants_1.JUNIE_SKILLS_PATH}`, verbose, dryRun);
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
await fs.rm(junieSkillsPath, { recursive: true, force: true });
|
|
285
|
+
(0, constants_1.logVerboseInfo)(`Removed ${constants_1.JUNIE_SKILLS_PATH} (skills disabled)`, verbose, dryRun);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
// Directory doesn't exist, nothing to clean
|
|
290
|
+
}
|
|
273
291
|
// Clean up .cursor/skills
|
|
274
292
|
try {
|
|
275
293
|
await fs.access(cursorSkillsPath);
|
|
@@ -395,6 +413,10 @@ async function propagateSkills(projectRoot, agents, skillsEnabled, verbose, dryR
|
|
|
395
413
|
(0, constants_1.logVerboseInfo)(`Copying skills to ${constants_1.GEMINI_SKILLS_PATH} for Gemini CLI`, verbose, dryRun);
|
|
396
414
|
await propagateSkillsForGemini(projectRoot, { dryRun });
|
|
397
415
|
}
|
|
416
|
+
if (selectedTargets.has('junie')) {
|
|
417
|
+
(0, constants_1.logVerboseInfo)(`Copying skills to ${constants_1.JUNIE_SKILLS_PATH} for Junie`, verbose, dryRun);
|
|
418
|
+
await propagateSkillsForJunie(projectRoot, { dryRun });
|
|
419
|
+
}
|
|
398
420
|
if (selectedTargets.has('cursor')) {
|
|
399
421
|
(0, constants_1.logVerboseInfo)(`Copying skills to ${constants_1.CURSOR_SKILLS_PATH} for Cursor`, verbose, dryRun);
|
|
400
422
|
await propagateSkillsForCursor(projectRoot, { dryRun });
|
|
@@ -809,6 +831,47 @@ async function propagateSkillsForGemini(projectRoot, options) {
|
|
|
809
831
|
}
|
|
810
832
|
return [];
|
|
811
833
|
}
|
|
834
|
+
/**
|
|
835
|
+
* Propagates skills for Junie by copying .ruler/skills to .junie/skills.
|
|
836
|
+
* Uses atomic replace to ensure safe overwriting of existing skills.
|
|
837
|
+
* Returns dry-run steps if dryRun is true, otherwise returns empty array.
|
|
838
|
+
*/
|
|
839
|
+
async function propagateSkillsForJunie(projectRoot, options) {
|
|
840
|
+
const skillsDir = path.join(projectRoot, constants_1.RULER_SKILLS_PATH);
|
|
841
|
+
const junieSkillsPath = path.join(projectRoot, constants_1.JUNIE_SKILLS_PATH);
|
|
842
|
+
const junieDir = path.dirname(junieSkillsPath);
|
|
843
|
+
try {
|
|
844
|
+
await fs.access(skillsDir);
|
|
845
|
+
}
|
|
846
|
+
catch {
|
|
847
|
+
return [];
|
|
848
|
+
}
|
|
849
|
+
if (options.dryRun) {
|
|
850
|
+
return [`Copy skills from ${constants_1.RULER_SKILLS_PATH} to ${constants_1.JUNIE_SKILLS_PATH}`];
|
|
851
|
+
}
|
|
852
|
+
await fs.mkdir(junieDir, { recursive: true });
|
|
853
|
+
const tempDir = path.join(junieDir, `skills.tmp-${Date.now()}`);
|
|
854
|
+
try {
|
|
855
|
+
await (0, SkillsUtils_1.copySkillsDirectory)(skillsDir, tempDir);
|
|
856
|
+
try {
|
|
857
|
+
await fs.rm(junieSkillsPath, { recursive: true, force: true });
|
|
858
|
+
}
|
|
859
|
+
catch {
|
|
860
|
+
// Target didn't exist, that's fine
|
|
861
|
+
}
|
|
862
|
+
await fs.rename(tempDir, junieSkillsPath);
|
|
863
|
+
}
|
|
864
|
+
catch (error) {
|
|
865
|
+
try {
|
|
866
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
867
|
+
}
|
|
868
|
+
catch {
|
|
869
|
+
// Ignore cleanup errors
|
|
870
|
+
}
|
|
871
|
+
throw error;
|
|
872
|
+
}
|
|
873
|
+
return [];
|
|
874
|
+
}
|
|
812
875
|
/**
|
|
813
876
|
* Propagates skills for Cursor by copying .ruler/skills to .cursor/skills.
|
|
814
877
|
* Uses atomic replace to ensure safe overwriting of existing skills.
|