@intellectronica/ruler 0.2.6 → 0.2.8

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 CHANGED
@@ -48,6 +48,7 @@ Ruler solves this by providing a **single source of truth** for all your AI agen
48
48
  | Firebase Studio | `.idx/airules.md` |
49
49
  | Open Hands | `.openhands/microagents/repo.md` and `.openhands/config.toml` |
50
50
  | Gemini CLI | `GEMINI.md` and `.gemini/settings.json` |
51
+ | Junie | `.junie/guidelines.md` |
51
52
 
52
53
  ## Getting Started
53
54
 
@@ -143,7 +144,7 @@ The `apply` command looks for `.ruler/` in the current directory tree, reading t
143
144
  | Option | Description |
144
145
  | ------------------------------ | --------------------------------------------------------- |
145
146
  | `--project-root <path>` | Path to your project's root (default: current directory) |
146
- | `--agents <agent1,agent2,...>` | Comma-separated list of agent names to target |
147
+ | `--agents <agent1,agent2,...>` | Comma-separated list of agent names to target (copilot, claude, codex, cursor, windsurf, cline, aider, firebase, gemini-cli, junie) |
147
148
  | `--config <path>` | Path to a custom `ruler.toml` configuration file |
148
149
  | `--mcp` / `--with-mcp` | Enable applying MCP server configurations (default: true) |
149
150
  | `--no-mcp` | Disable applying MCP server configurations |
@@ -240,6 +241,10 @@ enabled = true
240
241
  [agents.jules]
241
242
  enabled = true
242
243
 
244
+ [agents.junie]
245
+ enabled = true
246
+ output_path = ".junie/guidelines.md"
247
+
243
248
  # Agent-specific MCP configuration
244
249
  [agents.cursor.mcp]
245
250
  enabled = true
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.JunieAgent = void 0;
37
+ const path = __importStar(require("path"));
38
+ const FileSystemUtils_1 = require("../core/FileSystemUtils");
39
+ /**
40
+ * JetBrains Junie agent adapter.
41
+ */
42
+ class JunieAgent {
43
+ getIdentifier() {
44
+ return 'junie';
45
+ }
46
+ getName() {
47
+ return 'Junie';
48
+ }
49
+ async applyRulerConfig(concatenatedRules, projectRoot, rulerMcpJson, // eslint-disable-line @typescript-eslint/no-unused-vars
50
+ agentConfig) {
51
+ const output = agentConfig?.outputPath ?? this.getDefaultOutputPath(projectRoot);
52
+ await (0, FileSystemUtils_1.ensureDirExists)(path.dirname(output));
53
+ await (0, FileSystemUtils_1.backupFile)(output);
54
+ await (0, FileSystemUtils_1.writeGeneratedFile)(output, concatenatedRules);
55
+ }
56
+ getDefaultOutputPath(projectRoot) {
57
+ return path.join(projectRoot, '.junie', 'guidelines.md');
58
+ }
59
+ }
60
+ exports.JunieAgent = JunieAgent;
@@ -59,7 +59,7 @@ function run() {
59
59
  });
60
60
  y.option('agents', {
61
61
  type: 'string',
62
- description: 'Comma-separated list of agent identifiers: copilot, claude, codex, cursor, windsurf, cline, aider, firebase, gemini-cli',
62
+ description: 'Comma-separated list of agent identifiers: copilot, claude, codex, cursor, windsurf, cline, aider, firebase, gemini-cli, junie',
63
63
  });
64
64
  y.option('config', {
65
65
  type: 'string',
package/dist/lib.js CHANGED
@@ -51,6 +51,7 @@ const FirebaseAgent_1 = require("./agents/FirebaseAgent");
51
51
  const OpenHandsAgent_1 = require("./agents/OpenHandsAgent");
52
52
  const GeminiCliAgent_1 = require("./agents/GeminiCliAgent");
53
53
  const JulesAgent_1 = require("./agents/JulesAgent");
54
+ const JunieAgent_1 = require("./agents/JunieAgent");
54
55
  const merge_1 = require("./mcp/merge");
55
56
  const validate_1 = require("./mcp/validate");
56
57
  const mcp_1 = require("./paths/mcp");
@@ -102,6 +103,7 @@ const agents = [
102
103
  new OpenHandsAgent_1.OpenHandsAgent(),
103
104
  new GeminiCliAgent_1.GeminiCliAgent(),
104
105
  new JulesAgent_1.JulesAgent(),
106
+ new JunieAgent_1.JunieAgent(),
105
107
  ];
106
108
  /**
107
109
  * Applies ruler configurations for all supported AI agents.
@@ -199,6 +201,9 @@ async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cli
199
201
  const outputPaths = getAgentOutputPaths(agent, projectRoot, agentConfig);
200
202
  (0, constants_1.logVerbose)(`Agent ${agent.getName()} output paths: ${outputPaths.join(', ')}`, verbose);
201
203
  generatedPaths.push(...outputPaths);
204
+ // Also add the backup file paths to the gitignore list
205
+ const backupPaths = outputPaths.map((p) => `${p}.bak`);
206
+ generatedPaths.push(...backupPaths);
202
207
  if (dryRun) {
203
208
  (0, constants_1.logVerbose)(`DRY RUN: Would write rules to: ${outputPaths.join(', ')}`, verbose);
204
209
  }
@@ -217,6 +222,13 @@ async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cli
217
222
  (agentConfig?.mcp?.enabled ?? config.mcp?.enabled ?? true);
218
223
  const rulerMcpFile = path.join(rulerDir, 'mcp.json');
219
224
  if (dest && mcpEnabledForAgent) {
225
+ // Include MCP config file in .gitignore only if it's within the project directory
226
+ if (dest.startsWith(projectRoot)) {
227
+ const relativeDest = path.relative(projectRoot, dest);
228
+ generatedPaths.push(relativeDest);
229
+ // Also add the backup for the MCP file
230
+ generatedPaths.push(`${relativeDest}.bak`);
231
+ }
220
232
  if (agent.getIdentifier() === 'openhands') {
221
233
  // *** Special handling for Open Hands ***
222
234
  if (dryRun) {
@@ -225,8 +237,7 @@ async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cli
225
237
  else {
226
238
  await (0, propagateOpenHandsMcp_1.propagateMcpToOpenHands)(rulerMcpFile, dest);
227
239
  }
228
- // Include Open Hands config file in .gitignore
229
- generatedPaths.push(dest);
240
+ // Open Hands config file is already included above
230
241
  }
231
242
  else {
232
243
  if (rulerMcpJson) {
@@ -262,9 +273,9 @@ async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cli
262
273
  gitignoreEnabled = true; // Default enabled
263
274
  }
264
275
  if (gitignoreEnabled && generatedPaths.length > 0) {
265
- // Filter out .bak files as specified in requirements
266
- const pathsToIgnore = generatedPaths.filter((p) => !p.endsWith('.bak'));
267
- const uniquePaths = [...new Set(pathsToIgnore)];
276
+ const uniquePaths = [...new Set(generatedPaths)];
277
+ // Add wildcard pattern for backup files
278
+ uniquePaths.push('*.bak');
268
279
  if (uniquePaths.length > 0) {
269
280
  const actionPrefix = dryRun ? '[ruler:dry-run]' : '[ruler]';
270
281
  if (dryRun) {
package/dist/paths/mcp.js CHANGED
@@ -71,6 +71,9 @@ async function getNativeMcpPath(adapterName, projectRoot) {
71
71
  // For Open Hands, we target the main config file, not a separate mcp.json
72
72
  candidates.push(path.join(projectRoot, '.openhands', 'config.toml'));
73
73
  break;
74
+ case 'Gemini CLI':
75
+ candidates.push(path.join(projectRoot, '.gemini', 'settings.json'));
76
+ break;
74
77
  default:
75
78
  return null;
76
79
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intellectronica/ruler",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Ruler — apply the same rules to all coding agents",
5
5
  "main": "dist/lib.js",
6
6
  "scripts": {