@intellectronica/ruler 0.3.28 → 0.3.30
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 +48 -43
- package/dist/agents/CodexCliAgent.js +11 -4
- package/dist/agents/JetBrainsAiAssistantAgent.js +54 -0
- package/dist/agents/index.js +2 -0
- package/dist/cli/handlers.js +1 -1
- package/dist/core/apply-engine.js +35 -5
- package/dist/paths/mcp.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,38 +54,40 @@ Ruler solves this by providing a **single source of truth** for all your AI agen
|
|
|
54
54
|
|
|
55
55
|
## Supported AI Agents
|
|
56
56
|
|
|
57
|
-
| Agent | Rules File(s)
|
|
58
|
-
| ---------------- |
|
|
59
|
-
| AGENTS.md | `AGENTS.md`
|
|
60
|
-
| GitHub Copilot | `AGENTS.md`
|
|
61
|
-
| Claude Code | `CLAUDE.md`
|
|
62
|
-
| OpenAI Codex CLI | `AGENTS.md`
|
|
63
|
-
| Pi Coding Agent | `AGENTS.md`
|
|
64
|
-
| Jules | `AGENTS.md`
|
|
65
|
-
| Cursor | `AGENTS.md`
|
|
66
|
-
| Windsurf | `AGENTS.md`
|
|
67
|
-
| Cline | `.clinerules`
|
|
68
|
-
| Crush | `CRUSH.md`
|
|
69
|
-
| Amp | `AGENTS.md`
|
|
70
|
-
| Antigravity | `.agent/rules/ruler.md`
|
|
71
|
-
| Amazon Q CLI | `.amazonq/rules/ruler_q_rules.md`
|
|
72
|
-
| Aider | `AGENTS.md`, `.aider.conf.yml`
|
|
73
|
-
| Firebase Studio | `.idx/airules.md`
|
|
74
|
-
| Open Hands | `.openhands/microagents/repo.md`
|
|
75
|
-
| Gemini CLI | `AGENTS.md`
|
|
76
|
-
| Junie | `.junie/guidelines.md`
|
|
77
|
-
| AugmentCode | `.augment/rules/ruler_augment_instructions.md`
|
|
78
|
-
| Kilo Code | `AGENTS.md`
|
|
79
|
-
| OpenCode | `AGENTS.md`
|
|
80
|
-
| Goose | `.goosehints`
|
|
81
|
-
| Qwen Code | `AGENTS.md`
|
|
82
|
-
| RooCode | `AGENTS.md`
|
|
83
|
-
| Zed | `AGENTS.md`
|
|
84
|
-
| Trae AI | `.trae/rules/project_rules.md`
|
|
85
|
-
| Warp | `WARP.md`
|
|
86
|
-
| Kiro | `.kiro/steering/ruler_kiro_instructions.md`
|
|
87
|
-
| Firebender | `firebender.json`
|
|
88
|
-
|
|
|
57
|
+
| Agent | Rules File(s) | MCP Configuration / Notes | Skills Support / Location |
|
|
58
|
+
| ---------------- | ---------------------------------------------- | ------------------------------------------------ | ------------------------- |
|
|
59
|
+
| AGENTS.md | `AGENTS.md` | (pseudo-agent ensuring root `AGENTS.md` exists) | - |
|
|
60
|
+
| GitHub Copilot | `AGENTS.md` | `.vscode/mcp.json` | `.claude/skills/` |
|
|
61
|
+
| Claude Code | `CLAUDE.md` | `.mcp.json` | `.claude/skills/` |
|
|
62
|
+
| OpenAI Codex CLI | `AGENTS.md` | `.codex/config.toml` | `.codex/skills/` |
|
|
63
|
+
| Pi Coding Agent | `AGENTS.md` | - | `.pi/skills/` |
|
|
64
|
+
| Jules | `AGENTS.md` | - | - |
|
|
65
|
+
| Cursor | `AGENTS.md` | `.cursor/mcp.json` | `.cursor/skills/` |
|
|
66
|
+
| Windsurf | `AGENTS.md` | `.windsurf/mcp_config.json` | - |
|
|
67
|
+
| Cline | `.clinerules` | - | - |
|
|
68
|
+
| Crush | `CRUSH.md` | `.crush.json` | - |
|
|
69
|
+
| Amp | `AGENTS.md` | - | `.agents/skills/` |
|
|
70
|
+
| Antigravity | `.agent/rules/ruler.md` | - | `.agent/skills/` |
|
|
71
|
+
| Amazon Q CLI | `.amazonq/rules/ruler_q_rules.md` | `.amazonq/mcp.json` | - |
|
|
72
|
+
| Aider | `AGENTS.md`, `.aider.conf.yml` | `.mcp.json` | - |
|
|
73
|
+
| Firebase Studio | `.idx/airules.md` | `.idx/mcp.json` | - |
|
|
74
|
+
| Open Hands | `.openhands/microagents/repo.md` | `config.toml` | - |
|
|
75
|
+
| Gemini CLI | `AGENTS.md` | `.gemini/settings.json` | `.gemini/skills/` |
|
|
76
|
+
| Junie | `.junie/guidelines.md` | - | - |
|
|
77
|
+
| AugmentCode | `.augment/rules/ruler_augment_instructions.md` | - | - |
|
|
78
|
+
| Kilo Code | `AGENTS.md` | `.kilocode/mcp.json` | `.claude/skills/` |
|
|
79
|
+
| OpenCode | `AGENTS.md` | `opencode.json` | `.opencode/skill/` |
|
|
80
|
+
| Goose | `.goosehints` | - | `.agents/skills/` |
|
|
81
|
+
| Qwen Code | `AGENTS.md` | `.qwen/settings.json` | - |
|
|
82
|
+
| RooCode | `AGENTS.md` | `.roo/mcp.json` | `.roo/skills/` |
|
|
83
|
+
| Zed | `AGENTS.md` | `.zed/settings.json` (project root, never $HOME) | - |
|
|
84
|
+
| Trae AI | `.trae/rules/project_rules.md` | - | - |
|
|
85
|
+
| Warp | `WARP.md` | - | - |
|
|
86
|
+
| Kiro | `.kiro/steering/ruler_kiro_instructions.md` | `.kiro/settings/mcp.json` | - |
|
|
87
|
+
| Firebender | `firebender.json` | `firebender.json` (rules and MCP in same file) | - |
|
|
88
|
+
| Factory Droid | `AGENTS.md` | `.factory/mcp.json` | `.factory/skills/` |
|
|
89
|
+
| Mistral Vibe | `AGENTS.md` | `.vibe/config.toml` | `.vibe/skills/` |
|
|
90
|
+
| JetBrains AI Assistant | `.aiassistant/rules/AGENTS.md` | - | - |
|
|
89
91
|
|
|
90
92
|
## Getting Started
|
|
91
93
|
|
|
@@ -320,15 +322,15 @@ ruler revert [options]
|
|
|
320
322
|
|
|
321
323
|
### Options
|
|
322
324
|
|
|
323
|
-
| Option | Description
|
|
324
|
-
| ------------------------------ |
|
|
325
|
-
| `--project-root <path>` | Path to your project's root (default: current directory)
|
|
326
|
-
| `--agents <agent1,agent2,...>` | Comma-separated list of agent names to revert (agentsmd, aider, amazonqcli, amp, antigravity, augmentcode, claude, cline, codex, copilot, crush, cursor, firebase, firebender, gemini-cli, goose, jules, junie, kilocode, kiro, mistral, opencode, openhands, pi, qwen, roo, trae, warp, windsurf, zed) |
|
|
327
|
-
| `--config <path>` | Path to a custom `ruler.toml` configuration file
|
|
328
|
-
| `--keep-backups` | Keep backup files (.bak) after restoration (default: false)
|
|
329
|
-
| `--dry-run` | Preview changes without actually reverting files
|
|
330
|
-
| `--verbose` / `-v` | Display detailed output during execution
|
|
331
|
-
| `--local-only` | Only search for local .ruler directories, ignore global config
|
|
325
|
+
| Option | Description |
|
|
326
|
+
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
327
|
+
| `--project-root <path>` | Path to your project's root (default: current directory) |
|
|
328
|
+
| `--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) |
|
|
329
|
+
| `--config <path>` | Path to a custom `ruler.toml` configuration file |
|
|
330
|
+
| `--keep-backups` | Keep backup files (.bak) after restoration (default: false) |
|
|
331
|
+
| `--dry-run` | Preview changes without actually reverting files |
|
|
332
|
+
| `--verbose` / `-v` | Display detailed output during execution |
|
|
333
|
+
| `--local-only` | Only search for local .ruler directories, ignore global config |
|
|
332
334
|
|
|
333
335
|
### Common Examples
|
|
334
336
|
|
|
@@ -579,6 +581,7 @@ Skills are specialized knowledge packages that extend AI agent capabilities with
|
|
|
579
581
|
- **Goose**: `.agents/skills/`
|
|
580
582
|
- **Amp**: `.agents/skills/` (shared with Goose)
|
|
581
583
|
- **Antigravity**: `.agent/skills/`
|
|
584
|
+
- **Factory Droid**: `.factory/skills/`
|
|
582
585
|
- **Mistral Vibe**: `.vibe/skills/`
|
|
583
586
|
- **Roo Code**: `.roo/skills/`
|
|
584
587
|
- **Gemini CLI**: `.gemini/skills/`
|
|
@@ -643,6 +646,7 @@ When skills support is enabled and gitignore integration is active, Ruler automa
|
|
|
643
646
|
- `.pi/skills/` (for Pi Coding Agent)
|
|
644
647
|
- `.agents/skills/` (for Goose and Amp)
|
|
645
648
|
- `.agent/skills/` (for Antigravity)
|
|
649
|
+
- `.factory/skills/` (for Factory Droid)
|
|
646
650
|
- `.vibe/skills/` (for Mistral Vibe)
|
|
647
651
|
- `.roo/skills/` (for Roo Code)
|
|
648
652
|
- `.gemini/skills/` (for Gemini CLI)
|
|
@@ -652,7 +656,7 @@ to your `.gitignore` file within the managed Ruler block.
|
|
|
652
656
|
|
|
653
657
|
### Requirements
|
|
654
658
|
|
|
655
|
-
- **For agents with native skills support** (Claude Code, GitHub Copilot, Kilo Code, OpenAI Codex CLI, OpenCode, Pi Coding Agent, Goose, Amp, Antigravity, Mistral Vibe, Roo Code, Gemini CLI, Cursor): No additional requirements.
|
|
659
|
+
- **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.
|
|
656
660
|
|
|
657
661
|
### Validation
|
|
658
662
|
|
|
@@ -701,6 +705,7 @@ ruler apply
|
|
|
701
705
|
# - Pi Coding Agent: .pi/skills/my-skill/
|
|
702
706
|
# - Goose & Amp: .agents/skills/my-skill/
|
|
703
707
|
# - Antigravity: .agent/skills/my-skill/
|
|
708
|
+
# - Factory Droid: .factory/skills/my-skill/
|
|
704
709
|
# - Mistral Vibe: .vibe/skills/my-skill/
|
|
705
710
|
# - Roo Code: .roo/skills/my-skill/
|
|
706
711
|
# - Gemini CLI: .gemini/skills/my-skill/
|
|
@@ -830,7 +835,7 @@ jobs:
|
|
|
830
835
|
- uses: actions/checkout@v4
|
|
831
836
|
- uses: actions/setup-node@v4
|
|
832
837
|
with:
|
|
833
|
-
node-version: '
|
|
838
|
+
node-version: '20'
|
|
834
839
|
cache: 'npm'
|
|
835
840
|
|
|
836
841
|
- name: Install Ruler
|
|
@@ -102,9 +102,13 @@ class CodexCliAgent {
|
|
|
102
102
|
// Add the ruler servers
|
|
103
103
|
for (const [serverName, serverConfig] of Object.entries(rulerServers)) {
|
|
104
104
|
// Create a properly formatted MCP server entry
|
|
105
|
-
const mcpServer = {
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
const mcpServer = {};
|
|
106
|
+
if (serverConfig.command) {
|
|
107
|
+
mcpServer.command = serverConfig.command;
|
|
108
|
+
}
|
|
109
|
+
if (serverConfig.url) {
|
|
110
|
+
mcpServer.url = serverConfig.url;
|
|
111
|
+
}
|
|
108
112
|
if (serverConfig.args) {
|
|
109
113
|
mcpServer.args = serverConfig.args;
|
|
110
114
|
}
|
|
@@ -133,11 +137,14 @@ class CodexCliAgent {
|
|
|
133
137
|
config: path.join(projectRoot, '.codex', 'config.toml'),
|
|
134
138
|
};
|
|
135
139
|
}
|
|
140
|
+
getMcpServerKey() {
|
|
141
|
+
return 'mcp_servers';
|
|
142
|
+
}
|
|
136
143
|
supportsMcpStdio() {
|
|
137
144
|
return true;
|
|
138
145
|
}
|
|
139
146
|
supportsMcpRemote() {
|
|
140
|
-
return
|
|
147
|
+
return true;
|
|
141
148
|
}
|
|
142
149
|
supportsNativeSkills() {
|
|
143
150
|
return true;
|
|
@@ -0,0 +1,54 @@
|
|
|
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.JetBrainsAiAssistantAgent = void 0;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const AbstractAgent_1 = require("./AbstractAgent");
|
|
39
|
+
/**
|
|
40
|
+
* JetBrains AI Assistant agent adapter.
|
|
41
|
+
* Writes rules to .aiassistant/rules/AGENTS.md.
|
|
42
|
+
*/
|
|
43
|
+
class JetBrainsAiAssistantAgent extends AbstractAgent_1.AbstractAgent {
|
|
44
|
+
getIdentifier() {
|
|
45
|
+
return 'jetbrains-ai';
|
|
46
|
+
}
|
|
47
|
+
getName() {
|
|
48
|
+
return 'JetBrains AI Assistant';
|
|
49
|
+
}
|
|
50
|
+
getDefaultOutputPath(projectRoot) {
|
|
51
|
+
return path.join(projectRoot, '.aiassistant', 'rules', 'AGENTS.md');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.JetBrainsAiAssistantAgent = JetBrainsAiAssistantAgent;
|
package/dist/agents/index.js
CHANGED
|
@@ -35,6 +35,7 @@ const FactoryDroidAgent_1 = require("./FactoryDroidAgent");
|
|
|
35
35
|
const AntigravityAgent_1 = require("./AntigravityAgent");
|
|
36
36
|
const MistralVibeAgent_1 = require("./MistralVibeAgent");
|
|
37
37
|
const PiAgent_1 = require("./PiAgent");
|
|
38
|
+
const JetBrainsAiAssistantAgent_1 = require("./JetBrainsAiAssistantAgent");
|
|
38
39
|
exports.allAgents = [
|
|
39
40
|
new CopilotAgent_1.CopilotAgent(),
|
|
40
41
|
new ClaudeAgent_1.ClaudeAgent(),
|
|
@@ -67,6 +68,7 @@ exports.allAgents = [
|
|
|
67
68
|
new AntigravityAgent_1.AntigravityAgent(),
|
|
68
69
|
new MistralVibeAgent_1.MistralVibeAgent(),
|
|
69
70
|
new PiAgent_1.PiAgent(),
|
|
71
|
+
new JetBrainsAiAssistantAgent_1.JetBrainsAiAssistantAgent(),
|
|
70
72
|
];
|
|
71
73
|
/**
|
|
72
74
|
* Generates a comma-separated list of agent identifiers for CLI help text.
|
package/dist/cli/handlers.js
CHANGED
|
@@ -152,7 +152,7 @@ async function initHandler(argv) {
|
|
|
152
152
|
|
|
153
153
|
# --- Agent Specific Configurations ---
|
|
154
154
|
# You can enable/disable agents and override their default output paths here.
|
|
155
|
-
# Use lowercase agent identifiers: aider, amp, claude, cline, codex, copilot, cursor, kilocode, pi, windsurf
|
|
155
|
+
# Use lowercase agent identifiers: aider, amp, claude, cline, codex, copilot, cursor, jetbrains-ai, kilocode, pi, windsurf
|
|
156
156
|
|
|
157
157
|
# [agents.copilot]
|
|
158
158
|
# enabled = true
|
|
@@ -41,6 +41,7 @@ exports.applyConfigurationsToAgents = applyConfigurationsToAgents;
|
|
|
41
41
|
exports.updateGitignore = updateGitignore;
|
|
42
42
|
const path = __importStar(require("path"));
|
|
43
43
|
const fs_1 = require("fs");
|
|
44
|
+
const toml_1 = require("@iarna/toml");
|
|
44
45
|
const FileSystemUtils = __importStar(require("./FileSystemUtils"));
|
|
45
46
|
const RuleProcessor_1 = require("./RuleProcessor");
|
|
46
47
|
const ConfigLoader_1 = require("./ConfigLoader");
|
|
@@ -544,8 +545,28 @@ async function applyStandardMcpConfiguration(agent, filteredMcpJson, dest, agent
|
|
|
544
545
|
else if (agent.getIdentifier() === 'factory') {
|
|
545
546
|
mcpToMerge = transformMcpForFactoryDroid(filteredMcpJson);
|
|
546
547
|
}
|
|
547
|
-
const
|
|
548
|
-
const
|
|
548
|
+
const CODEX_AGENT_ID = 'codex';
|
|
549
|
+
const isCodexToml = agent.getIdentifier() === CODEX_AGENT_ID && dest.endsWith('.toml');
|
|
550
|
+
let existing = await (0, mcp_1.readNativeMcp)(dest);
|
|
551
|
+
if (isCodexToml) {
|
|
552
|
+
try {
|
|
553
|
+
const tomlContent = await fs_1.promises.readFile(dest, 'utf8');
|
|
554
|
+
existing = (0, toml_1.parse)(tomlContent);
|
|
555
|
+
}
|
|
556
|
+
catch (error) {
|
|
557
|
+
(0, constants_1.logVerbose)(`Failed to read Codex MCP TOML at ${dest}: ${error.message}`, verbose);
|
|
558
|
+
// ignore missing or invalid TOML, fall back to previously read value
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
let merged = (0, merge_1.mergeMcp)(existing, mcpToMerge, strategy, serverKey);
|
|
562
|
+
if (isCodexToml) {
|
|
563
|
+
const { [serverKey]: servers, ...rest } = merged;
|
|
564
|
+
merged = {
|
|
565
|
+
...rest,
|
|
566
|
+
// Codex CLI expects MCP servers under mcp_servers in config.toml.
|
|
567
|
+
mcp_servers: servers ?? {},
|
|
568
|
+
};
|
|
569
|
+
}
|
|
549
570
|
// Firebase Studio (IDX) expects no "type" fields in .idx/mcp.json server entries.
|
|
550
571
|
// Sanitize merged config by stripping 'type' from each server when targeting Firebase.
|
|
551
572
|
const sanitizeForFirebase = (obj) => {
|
|
@@ -593,14 +614,23 @@ async function applyStandardMcpConfiguration(agent, filteredMcpJson, dest, agent
|
|
|
593
614
|
let toWrite = sanitizeForFirebase(merged);
|
|
594
615
|
toWrite = sanitizeForGemini(toWrite);
|
|
595
616
|
// Only backup and write if content would actually change (idempotent)
|
|
596
|
-
const currentContent =
|
|
597
|
-
|
|
617
|
+
const currentContent = isCodexToml
|
|
618
|
+
? (0, toml_1.stringify)(existing)
|
|
619
|
+
: JSON.stringify(existing, null, 2);
|
|
620
|
+
const newContent = isCodexToml
|
|
621
|
+
? (0, toml_1.stringify)(toWrite)
|
|
622
|
+
: JSON.stringify(toWrite, null, 2);
|
|
598
623
|
if (currentContent !== newContent) {
|
|
599
624
|
if (backup) {
|
|
600
625
|
const { backupFile } = await Promise.resolve().then(() => __importStar(require('../core/FileSystemUtils')));
|
|
601
626
|
await backupFile(dest);
|
|
602
627
|
}
|
|
603
|
-
|
|
628
|
+
if (isCodexToml) {
|
|
629
|
+
await FileSystemUtils.writeGeneratedFile(dest, (0, toml_1.stringify)(toWrite));
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
await (0, mcp_1.writeNativeMcp)(dest, toWrite);
|
|
633
|
+
}
|
|
604
634
|
}
|
|
605
635
|
else {
|
|
606
636
|
(0, constants_1.logVerbose)(`MCP config for ${agent.getName()} is already up to date - skipping backup and write`, verbose);
|
package/dist/paths/mcp.js
CHANGED
|
@@ -59,7 +59,7 @@ async function getNativeMcpPath(adapterName, projectRoot) {
|
|
|
59
59
|
candidates.push(path.join(projectRoot, '.mcp.json'));
|
|
60
60
|
break;
|
|
61
61
|
case 'OpenAI Codex CLI':
|
|
62
|
-
candidates.push(path.join(projectRoot, '.codex', 'config.
|
|
62
|
+
candidates.push(path.join(projectRoot, '.codex', 'config.toml'));
|
|
63
63
|
break;
|
|
64
64
|
case 'Aider':
|
|
65
65
|
candidates.push(path.join(projectRoot, '.mcp.json'));
|