@intellectronica/ruler 0.3.6 → 0.3.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 CHANGED
@@ -57,18 +57,19 @@ Ruler solves this by providing a **single source of truth** for all your AI agen
57
57
  | Agent | Rules File(s) | MCP Configuration / Notes |
58
58
  | ---------------- | ------------------------------------------------ | ------------------------------------------------ |
59
59
  | AGENTS.md | `AGENTS.md` | (pseudo-agent ensuring root `AGENTS.md` exists) |
60
- | GitHub Copilot | `.github/copilot-instructions.md` | `.vscode/mcp.json` |
60
+ | GitHub Copilot | `AGENTS.md`, `.github/copilot-instructions.md` | `.vscode/mcp.json` |
61
61
  | Claude Code | `CLAUDE.md` | `.mcp.json` |
62
62
  | OpenAI Codex CLI | `AGENTS.md` | `.codex/config.toml` |
63
63
  | Jules | `AGENTS.md` | - |
64
64
  | Cursor | `.cursor/rules/ruler_cursor_instructions.mdc` | `.cursor/mcp.json` |
65
65
  | Windsurf | `.windsurf/rules/ruler_windsurf_instructions.md` | - |
66
66
  | Cline | `.clinerules` | - |
67
+ | Crush | `CRUSH.md` | `.crush.json` |
67
68
  | Amp | `AGENTS.md` | - |
68
69
  | Amazon Q CLI | `.amazonq/rules/ruler_q_rules.md` | `.amazonq/mcp.json` |
69
70
  | Aider | `AGENTS.md`, `.aider.conf.yml` | `.mcp.json` |
70
71
  | Firebase Studio | `.idx/airules.md` | - |
71
- | Open Hands | `.openhands/microagents/repo.md` | `.openhands/config.toml` |
72
+ | Open Hands | `.openhands/microagents/repo.md` | `config.toml` |
72
73
  | Gemini CLI | `AGENTS.md` | `.gemini/settings.json` |
73
74
  | Junie | `.junie/guidelines.md` | - |
74
75
  | AugmentCode | `.augment/rules/ruler_augment_instructions.md` | `.vscode/settings.json` |
@@ -78,15 +79,12 @@ Ruler solves this by providing a **single source of truth** for all your AI agen
78
79
  | Qwen Code | `AGENTS.md` | `.qwen/settings.json` |
79
80
  | RooCode | `AGENTS.md` | `.roo/mcp.json` |
80
81
  | Zed | `AGENTS.md` | `.zed/settings.json` (project root, never $HOME) |
82
+ | Trae AI | `.trae/rules/project_rules.md` | - |
81
83
  | Warp | `WARP.md` | - |
82
84
  | Kiro | `.kiro/steering/ruler_kiro_instructions.md` | - |
83
85
 
84
86
  ## Getting Started
85
87
 
86
- ### Prerequisites
87
-
88
- Node.js 18.x or higher is required.
89
-
90
88
  ### Installation
91
89
 
92
90
  **Global Installation (Recommended for CLI use):**
@@ -216,13 +214,16 @@ The `apply` command looks for `.ruler/` in the current directory tree, reading t
216
214
  | Option | Description |
217
215
  | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
218
216
  | `--project-root <path>` | Path to your project's root (default: current directory) |
219
- | `--agents <agent1,agent2,...>` | Comma-separated list of agent names to target (agentsmd, amp, copilot, claude, codex, cursor, windsurf, cline, aider, firebase, gemini-cli, junie, augmentcode, kilocode, warp, roo) |
217
+ | `--agents <agent1,agent2,...>` | Comma-separated list of agent names to target (agentsmd, amazonqcli, amp, copilot, claude, codex, cursor, windsurf, cline, aider, firebase, openhands, gemini-cli, jules, junie, augmentcode, kilocode, opencode, goose, crush, zed, qwen, kiro, warp, roo, trae) |
220
218
  | `--config <path>` | Path to a custom `ruler.toml` configuration file |
221
219
  | `--mcp` / `--with-mcp` | Enable applying MCP server configurations (default: true) |
222
220
  | `--no-mcp` | Disable applying MCP server configurations |
223
221
  | `--mcp-overwrite` | Overwrite native MCP config entirely instead of merging |
224
222
  | `--gitignore` | Enable automatic .gitignore updates (default: true) |
225
223
  | `--no-gitignore` | Disable automatic .gitignore updates |
224
+ | `--nested` | Enable nested rule loading from nested .ruler directories (default: disabled) |
225
+ | `--backup` | Enable/disable creation of .bak backup files (default: enabled) |
226
+ | `--dry-run` | Preview changes without writing files |
226
227
  | `--local-only` | Do not look for configuration in `$XDG_CONFIG_HOME` |
227
228
  | `--verbose` / `-v` | Display detailed output during execution |
228
229
 
@@ -252,6 +253,12 @@ ruler apply --agents firebase
252
253
  ruler apply --agents warp
253
254
  ```
254
255
 
256
+ **Apply rules only to Trae AI:**
257
+
258
+ ```bash
259
+ ruler apply --agents trae
260
+ ```
261
+
255
262
  **Apply rules only to RooCode:**
256
263
 
257
264
  ```bash
@@ -300,7 +307,7 @@ ruler revert [options]
300
307
  | Option | Description |
301
308
  | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
302
309
  | `--project-root <path>` | Path to your project's root (default: current directory) |
303
- | `--agents <agent1,agent2,...>` | Comma-separated list of agent names to revert (agentsmd, amp, copilot, claude, codex, cursor, windsurf, cline, aider, firebase, gemini-cli, junie, kilocode, opencode, warp) |
310
+ | `--agents <agent1,agent2,...>` | Comma-separated list of agent names to revert (agentsmd, amazonqcli, amp, copilot, claude, codex, cursor, windsurf, cline, aider, firebase, openhands, gemini-cli, jules, junie, augmentcode, kilocode, opencode, goose, crush, zed, qwen, kiro, warp, roo, trae) |
304
311
  | `--config <path>` | Path to a custom `ruler.toml` configuration file |
305
312
  | `--keep-backups` | Keep backup files (.bak) after restoration (default: false) |
306
313
  | `--dry-run` | Preview changes without actually reverting files |
@@ -616,7 +623,7 @@ This creates context-specific instructions for different parts of your project w
616
623
  2. Commit the `.ruler` directory to your repository
617
624
  3. Team members pull changes and run `ruler apply` to update their local AI agent configurations
618
625
 
619
- ### Scenario 3: Project-Specific Context for AI
626
+ ### Scenario 4: Project-Specific Context for AI
620
627
 
621
628
  1. Detail your project's architecture in `.ruler/project_overview.md`
622
629
  2. Describe primary data structures in `.ruler/data_models.md`
@@ -792,43 +799,5 @@ MIT
792
799
 
793
800
  ---
794
801
 
795
- ## Development and Testing
796
-
797
- ### Running Tests
798
-
799
- The project includes comprehensive test coverage with unit, integration, and end-to-end tests:
800
-
801
- ```bash
802
- # Run all tests
803
- npm test
804
-
805
- # Run with coverage
806
- npm run test:coverage
807
-
808
- # Run integration tests specifically
809
- npm run test:integration
810
-
811
- # Run tests in watch mode
812
- npm run test:watch
813
- ```
814
-
815
- ### Integration Testing
816
-
817
- The project includes comprehensive integration tests that validate the complete CLI workflow:
818
-
819
- - **`npm run test:integration`**: Runs a full end-to-end integration test that:
820
- 1. Creates a temporary test directory
821
- 2. Runs `ruler init` to set up the initial structure
822
- 3. Creates custom `ruler.toml` with MCP servers (both stdio and remote)
823
- 4. Creates sample `AGENTS.md` and additional markdown files for concatenation
824
- 5. Runs `ruler apply` to generate all agent configuration files
825
- 6. Inspects and validates all generated files contain expected content
826
- 7. Outputs the content of all generated files for manual verification
827
- 8. Validates MCP server configurations were properly applied
828
-
829
- This integration test ensures the entire CLI workflow functions correctly and can be used for manual testing or CI validation.
830
-
831
- ---
832
-
833
802
  © Eleanor Berger
834
803
  [ai.intellectronica.net](https://ai.intellectronica.net/)
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.allAgents = exports.AbstractAgent = void 0;
4
+ exports.getAgentIdentifiersForCliHelp = getAgentIdentifiersForCliHelp;
4
5
  const AbstractAgent_1 = require("./AbstractAgent");
5
6
  Object.defineProperty(exports, "AbstractAgent", { enumerable: true, get: function () { return AbstractAgent_1.AbstractAgent; } });
6
7
  const CopilotAgent_1 = require("./CopilotAgent");
@@ -57,3 +58,18 @@ exports.allAgents = [
57
58
  new TraeAgent_1.TraeAgent(),
58
59
  new AmazonQCliAgent_1.AmazonQCliAgent(),
59
60
  ];
61
+ /**
62
+ * Generates a comma-separated list of agent identifiers for CLI help text.
63
+ * Returns identifiers in alphabetical order, with 'agentsmd' always first.
64
+ */
65
+ function getAgentIdentifiersForCliHelp() {
66
+ const identifiers = exports.allAgents.map((agent) => agent.getIdentifier());
67
+ const sorted = identifiers.sort();
68
+ // Ensure agentsmd is first (it should already be first alphabetically, but let's be explicit)
69
+ const agentsMdIndex = sorted.indexOf('agentsmd');
70
+ if (agentsMdIndex > 0) {
71
+ const agentsmd = sorted.splice(agentsMdIndex, 1)[0];
72
+ sorted.unshift(agentsmd);
73
+ }
74
+ return sorted.join(', ');
75
+ }
@@ -7,6 +7,7 @@ exports.run = run;
7
7
  const yargs_1 = __importDefault(require("yargs"));
8
8
  const helpers_1 = require("yargs/helpers");
9
9
  const handlers_1 = require("./handlers");
10
+ const index_1 = require("../agents/index");
10
11
  /**
11
12
  * Sets up and parses CLI commands.
12
13
  */
@@ -23,7 +24,7 @@ function run() {
23
24
  })
24
25
  .option('agents', {
25
26
  type: 'string',
26
- description: 'Comma-separated list of agent identifiers: amp, copilot, claude, codex, cursor, windsurf, cline, aider, firebase, gemini-cli, junie, kilocode, opencode, crush, zed, qwen',
27
+ description: `Comma-separated list of agent identifiers: ${(0, index_1.getAgentIdentifiersForCliHelp)()}`,
27
28
  })
28
29
  .option('config', {
29
30
  type: 'string',
@@ -93,7 +94,7 @@ function run() {
93
94
  })
94
95
  .option('agents', {
95
96
  type: 'string',
96
- description: 'Comma-separated list of agent identifiers: amp, copilot, claude, codex, cursor, windsurf, cline, aider, firebase, gemini-cli, junie, kilocode, opencode, crush, zed, qwen',
97
+ description: `Comma-separated list of agent identifiers: ${(0, index_1.getAgentIdentifiersForCliHelp)()}`,
97
98
  })
98
99
  .option('config', {
99
100
  type: 'string',
package/dist/constants.js CHANGED
@@ -4,6 +4,10 @@ exports.DEFAULT_RULES_FILENAME = exports.ERROR_PREFIX = void 0;
4
4
  exports.actionPrefix = actionPrefix;
5
5
  exports.createRulerError = createRulerError;
6
6
  exports.logVerbose = logVerbose;
7
+ exports.logInfo = logInfo;
8
+ exports.logWarn = logWarn;
9
+ exports.logError = logError;
10
+ exports.logVerboseInfo = logVerboseInfo;
7
11
  exports.ERROR_PREFIX = '[ruler]';
8
12
  // Centralized default rules filename. Now points to 'AGENTS.md'.
9
13
  // Legacy '.ruler/instructions.md' is still supported as a fallback with a warning.
@@ -22,3 +26,26 @@ function logVerbose(message, isVerbose) {
22
26
  console.error(`[ruler:verbose] ${message}`);
23
27
  }
24
28
  }
29
+ /**
30
+ * Centralized logging functions with consistent output streams and prefixing.
31
+ * - info/verbose go to stdout (user-visible progress)
32
+ * - warn/error go to stderr (problems)
33
+ */
34
+ function logInfo(message, dryRun = false) {
35
+ const prefix = actionPrefix(dryRun);
36
+ console.log(`${prefix} ${message}`);
37
+ }
38
+ function logWarn(message, dryRun = false) {
39
+ const prefix = actionPrefix(dryRun);
40
+ console.warn(`${prefix} ${message}`);
41
+ }
42
+ function logError(message, dryRun = false) {
43
+ const prefix = actionPrefix(dryRun);
44
+ console.error(`${prefix} ${message}`);
45
+ }
46
+ function logVerboseInfo(message, isVerbose, dryRun = false) {
47
+ if (isVerbose) {
48
+ const prefix = actionPrefix(dryRun);
49
+ console.log(`${prefix} ${message}`);
50
+ }
51
+ }
@@ -121,7 +121,7 @@ async function warnAboutLegacyMcpJson(rulerDir) {
121
121
  try {
122
122
  const legacyMcpPath = path.join(rulerDir, 'mcp.json');
123
123
  await (await Promise.resolve().then(() => __importStar(require('fs/promises')))).access(legacyMcpPath);
124
- console.warn('[ruler] Warning: Using legacy .ruler/mcp.json. Please migrate to ruler.toml. This fallback will be removed in a future release.');
124
+ (0, constants_1.logWarn)('Warning: Using legacy .ruler/mcp.json. Please migrate to ruler.toml. This fallback will be removed in a future release.');
125
125
  }
126
126
  catch {
127
127
  // ignore
@@ -174,7 +174,7 @@ async function loadSingleConfiguration(projectRoot, configPath, localOnly) {
174
174
  async function processHierarchicalConfigurations(agents, configurations, verbose, dryRun, cliMcpEnabled, cliMcpStrategy, backup = true) {
175
175
  const allGeneratedPaths = [];
176
176
  for (const config of configurations) {
177
- console.log(`[ruler] Processing .ruler directory: ${config.rulerDir}`);
177
+ (0, constants_1.logVerboseInfo)(`Processing .ruler directory: ${config.rulerDir}`, verbose, dryRun);
178
178
  const rulerRoot = path.dirname(config.rulerDir);
179
179
  const paths = await applyConfigurationsToAgents(agents, config.concatenatedRules, config.rulerMcpJson, config.config, rulerRoot, verbose, dryRun, cliMcpEnabled, cliMcpStrategy, backup);
180
180
  allGeneratedPaths.push(...paths);
@@ -211,8 +211,7 @@ async function applyConfigurationsToAgents(agents, concatenatedRules, rulerMcpJs
211
211
  const generatedPaths = [];
212
212
  let agentsMdWritten = false;
213
213
  for (const agent of agents) {
214
- const prefix = (0, constants_1.actionPrefix)(dryRun);
215
- console.log(`${prefix} Applying rules for ${agent.getName()}...`);
214
+ (0, constants_1.logInfo)(`Applying rules for ${agent.getName()}...`, dryRun);
216
215
  (0, constants_1.logVerbose)(`Processing agent: ${agent.getName()}`, verbose);
217
216
  const agentConfig = config.agentConfigs[agent.getIdentifier()];
218
217
  // Collect output paths for .gitignore
@@ -309,6 +308,13 @@ async function applyMcpConfiguration(agent, filteredMcpJson, dest, agentConfig,
309
308
  if (agent.getIdentifier() === 'opencode') {
310
309
  return await applyOpenCodeMcpConfiguration(filteredMcpJson, dest, dryRun, verbose, backup);
311
310
  }
311
+ // Agents that handle MCP configuration internally should not have external MCP handling
312
+ if (agent.getIdentifier() === 'zed' ||
313
+ agent.getIdentifier() === 'gemini-cli' ||
314
+ agent.getIdentifier() === 'amazon-q-cli') {
315
+ (0, constants_1.logVerbose)(`Skipping external MCP config for ${agent.getName()} - handled internally by agent`, verbose);
316
+ return;
317
+ }
312
318
  return await applyStandardMcpConfiguration(agent, filteredMcpJson, dest, agentConfig, config, cliMcpStrategy, dryRun, verbose, backup);
313
319
  }
314
320
  async function applyOpenHandsMcpConfiguration(filteredMcpJson, dest, dryRun, verbose, backup = true) {
@@ -380,13 +386,12 @@ async function updateGitignore(projectRoot, generatedPaths, config, cliGitignore
380
386
  // Note: Individual backup patterns are added per-file in the collection phase
381
387
  // No need to add a broad *.bak pattern here
382
388
  if (uniquePaths.length > 0) {
383
- const prefix = (0, constants_1.actionPrefix)(dryRun);
384
389
  if (dryRun) {
385
- console.log(`${prefix} Would update .gitignore with ${uniquePaths.length} unique path(s): ${uniquePaths.join(', ')}`);
390
+ (0, constants_1.logInfo)(`Would update .gitignore with ${uniquePaths.length} unique path(s): ${uniquePaths.join(', ')}`, dryRun);
386
391
  }
387
392
  else {
388
393
  await (0, GitignoreUtils_1.updateGitignore)(projectRoot, uniquePaths);
389
- console.log(`${prefix} Updated .gitignore with ${uniquePaths.length} unique path(s) in the Ruler block.`);
394
+ (0, constants_1.logInfo)(`Updated .gitignore with ${uniquePaths.length} unique path(s) in the Ruler block.`, dryRun);
390
395
  }
391
396
  }
392
397
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intellectronica/ruler",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "Ruler — apply the same rules to all coding agents",
5
5
  "main": "dist/lib.js",
6
6
  "scripts": {