@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 +16 -47
- package/dist/agents/index.js +16 -0
- package/dist/cli/commands.js +3 -2
- package/dist/constants.js +27 -0
- package/dist/core/apply-engine.js +12 -7
- package/package.json +1 -1
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`
|
|
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` |
|
|
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
|
|
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/)
|
package/dist/agents/index.js
CHANGED
|
@@ -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
|
+
}
|
package/dist/cli/commands.js
CHANGED
|
@@ -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:
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
394
|
+
(0, constants_1.logInfo)(`Updated .gitignore with ${uniquePaths.length} unique path(s) in the Ruler block.`, dryRun);
|
|
390
395
|
}
|
|
391
396
|
}
|
|
392
397
|
}
|