@intellectronica/ruler 0.3.35 → 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 +18 -11
- package/dist/agents/JunieAgent.js +9 -0
- package/dist/constants.js +2 -1
- package/dist/core/SkillsProcessor.js +64 -1
- package/dist/core/revert-engine.js +1 -0
- package/dist/paths/mcp.js +3 -0
- 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` |
|
|
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)
|
|
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, 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
|
|
328
|
+
| Option | Description |
|
|
329
|
+
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
330
|
+
| `--project-root <path>` | Path to your project's root (default: current directory) |
|
|
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 |
|
|
337
337
|
|
|
338
338
|
### Common Examples
|
|
339
339
|
|
|
@@ -447,6 +447,10 @@ enabled = true
|
|
|
447
447
|
enabled = true
|
|
448
448
|
output_path = ".junie/guidelines.md"
|
|
449
449
|
|
|
450
|
+
[agents.junie.mcp]
|
|
451
|
+
enabled = true
|
|
452
|
+
merge_strategy = "merge"
|
|
453
|
+
|
|
450
454
|
# Agent-specific MCP configuration
|
|
451
455
|
[agents.cursor.mcp]
|
|
452
456
|
enabled = true
|
|
@@ -590,6 +594,7 @@ Skills are specialized knowledge packages that extend AI agent capabilities with
|
|
|
590
594
|
- **Mistral Vibe**: `.vibe/skills/`
|
|
591
595
|
- **Roo Code**: `.roo/skills/`
|
|
592
596
|
- **Gemini CLI**: `.gemini/skills/`
|
|
597
|
+
- **Junie**: `.junie/skills/`
|
|
593
598
|
- **Cursor**: `.cursor/skills/`
|
|
594
599
|
|
|
595
600
|
### Skills Directory Structure
|
|
@@ -655,13 +660,14 @@ When skills support is enabled and gitignore integration is active, Ruler automa
|
|
|
655
660
|
- `.vibe/skills/` (for Mistral Vibe)
|
|
656
661
|
- `.roo/skills/` (for Roo Code)
|
|
657
662
|
- `.gemini/skills/` (for Gemini CLI)
|
|
663
|
+
- `.junie/skills/` (for Junie)
|
|
658
664
|
- `.cursor/skills/` (for Cursor)
|
|
659
665
|
|
|
660
666
|
to your `.gitignore` file within the managed Ruler block.
|
|
661
667
|
|
|
662
668
|
### Requirements
|
|
663
669
|
|
|
664
|
-
- **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.
|
|
665
671
|
|
|
666
672
|
### Validation
|
|
667
673
|
|
|
@@ -714,6 +720,7 @@ ruler apply
|
|
|
714
720
|
# - Mistral Vibe: .vibe/skills/my-skill/
|
|
715
721
|
# - Roo Code: .roo/skills/my-skill/
|
|
716
722
|
# - Gemini CLI: .gemini/skills/my-skill/
|
|
723
|
+
# - Junie: .junie/skills/my-skill/
|
|
717
724
|
# - Cursor: .cursor/skills/my-skill/
|
|
718
725
|
```
|
|
719
726
|
|
|
@@ -49,5 +49,14 @@ class JunieAgent extends AbstractAgent_1.AbstractAgent {
|
|
|
49
49
|
getDefaultOutputPath(projectRoot) {
|
|
50
50
|
return path.join(projectRoot, '.junie', 'guidelines.md');
|
|
51
51
|
}
|
|
52
|
+
supportsMcpStdio() {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
supportsMcpRemote() {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
supportsNativeSkills() {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
52
61
|
}
|
|
53
62
|
exports.JunieAgent = JunieAgent;
|
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.
|
package/dist/paths/mcp.js
CHANGED
|
@@ -71,6 +71,9 @@ async function getNativeMcpPath(adapterName, projectRoot) {
|
|
|
71
71
|
case 'Gemini CLI':
|
|
72
72
|
candidates.push(path.join(projectRoot, '.gemini', 'settings.json'));
|
|
73
73
|
break;
|
|
74
|
+
case 'Junie':
|
|
75
|
+
candidates.push(path.join(projectRoot, '.junie', 'mcp', 'mcp.json'));
|
|
76
|
+
break;
|
|
74
77
|
case 'Qwen Code':
|
|
75
78
|
candidates.push(path.join(projectRoot, '.qwen', 'settings.json'));
|
|
76
79
|
break;
|