@intellectronica/ruler 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Eleanor Berger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # Ruler
2
+
3
+ A CLI tool to manage custom rules and configs across different AI coding agents.
4
+
5
+ ## Features
6
+
7
+ - Centralise AI agent instructions in a single `.ruler/` directory
8
+ - Distribute rules to supported agents (GitHub Copilot, Claude Code, OpenAI Codex CLI, Cursor, Windsurf, Cline, Aider)
9
+ - Extensible architecture: add new agent adapters easily
10
+
11
+ ## Installation
12
+
13
+ Install globally:
14
+
15
+ ```bash
16
+ npm install -g @intellectronica/ruler
17
+ ```
18
+
19
+ Or use npx:
20
+
21
+ ```bash
22
+ npx @intellectronica/ruler apply
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ Create a `.ruler/` directory at your project root and add Markdown files defining your rules:
28
+
29
+ ```
30
+ .ruler/
31
+ ├── coding_guidelines.md
32
+ └── style_guide.md
33
+ ```
34
+
35
+ Run the apply command:
36
+
37
+ ```bash
38
+ ruler apply [--project-root <path>] [--agents <agent1,agent2,...>]
39
+ ```
40
+
41
+ Use `--agents` to specify a comma-separated list of agent names (case-insensitive substrings) to limit which agents the rules are applied to.
42
+
43
+ The command will read all `.md` files under `.ruler/`, concatenate their contents, and generate/update configuration files for the following agents:
44
+
45
+ | Agent | File(s) Created/Updated |
46
+ | ---------------------- | ----------------------------------------------------------- |
47
+ | GitHub Copilot | `.github/copilot-instructions.md` |
48
+ | Claude Code | `CLAUDE.md` |
49
+ | OpenAI Codex CLI | `AGENTS.md` |
50
+ | Cursor | `.cursor/rules/ruler_cursor_instructions.md` |
51
+ | Windsurf | `.windsurf/rules/ruler_windsurf_instructions.md` |
52
+ | Cline | `.clinerules` |
53
+ | Aider | `ruler_aider_instructions.md` <br>and updates `.aider.conf.yml` |
54
+
55
+ ## Development
56
+
57
+ Clone the repository and install dependencies:
58
+
59
+ ```bash
60
+ git clone https://github.com/intellectronica/ruler.git
61
+ cd ruler
62
+ npm install
63
+ npm run build
64
+ ```
65
+
66
+ Run linting and formatting checks:
67
+
68
+ ```bash
69
+ npm run lint
70
+ npm run format
71
+ ```
72
+
73
+ Run tests:
74
+
75
+ ```bash
76
+ npm test
77
+ ```
78
+
79
+ End-to-end tests (run build before tests):
80
+
81
+ ```bash
82
+ npm run build && npm test
83
+ ```
84
+
85
+ ### Roadmap
86
+ - [ ] Support for MCP servers config
87
+ - [ ] Support for transforming and rewriting the rules using AI
88
+ - [ ] Support "harmonisation" (reading existing rules of specific agents and combining them with the master config)
89
+ - [ ] Support for additional agents
90
+ - [ ] Support for agent-specific features (for example: apply rules in copilot)
91
+
92
+ ## Contributing
93
+
94
+ Contributions are welcome! Please open issues or pull requests on GitHub.
95
+
96
+ ## License
97
+
98
+ MIT
99
+
100
+ ---
101
+
102
+ © Eleanor Berger
103
+
104
+ [ai.intellectronica.net](https://ai.intellectronica.net/)
@@ -0,0 +1,73 @@
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.AiderAgent = void 0;
37
+ const path = __importStar(require("path"));
38
+ const FileSystemUtils_1 = require("../core/FileSystemUtils");
39
+ const fs = __importStar(require("fs/promises"));
40
+ const yaml = __importStar(require("js-yaml"));
41
+ /**
42
+ * Aider agent adapter (stub implementation).
43
+ */
44
+ class AiderAgent {
45
+ getName() {
46
+ return 'Aider';
47
+ }
48
+ async applyRulerConfig(concatenatedRules, projectRoot) {
49
+ const mdFile = path.join(projectRoot, 'ruler_aider_instructions.md');
50
+ await (0, FileSystemUtils_1.backupFile)(mdFile);
51
+ await (0, FileSystemUtils_1.writeGeneratedFile)(mdFile, concatenatedRules);
52
+ const cfgPath = path.join(projectRoot, '.aider.conf.yml');
53
+ let doc = {};
54
+ try {
55
+ await fs.access(cfgPath);
56
+ await (0, FileSystemUtils_1.backupFile)(cfgPath);
57
+ const raw = await fs.readFile(cfgPath, 'utf8');
58
+ doc = (yaml.load(raw) || {});
59
+ }
60
+ catch {
61
+ doc = {};
62
+ }
63
+ if (!Array.isArray(doc.read)) {
64
+ doc.read = [];
65
+ }
66
+ if (!doc.read.includes('ruler_aider_instructions.md')) {
67
+ doc.read.push('ruler_aider_instructions.md');
68
+ }
69
+ const yamlStr = yaml.dump(doc);
70
+ await (0, FileSystemUtils_1.writeGeneratedFile)(cfgPath, yamlStr);
71
+ }
72
+ }
73
+ exports.AiderAgent = AiderAgent;
@@ -0,0 +1,52 @@
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.ClaudeAgent = void 0;
37
+ const path = __importStar(require("path"));
38
+ const FileSystemUtils_1 = require("../core/FileSystemUtils");
39
+ /**
40
+ * Claude Code agent adapter (stub implementation).
41
+ */
42
+ class ClaudeAgent {
43
+ getName() {
44
+ return 'Claude Code';
45
+ }
46
+ async applyRulerConfig(concatenatedRules, projectRoot) {
47
+ const target = path.join(projectRoot, 'CLAUDE.md');
48
+ await (0, FileSystemUtils_1.backupFile)(target);
49
+ await (0, FileSystemUtils_1.writeGeneratedFile)(target, concatenatedRules);
50
+ }
51
+ }
52
+ exports.ClaudeAgent = ClaudeAgent;
@@ -0,0 +1,52 @@
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.ClineAgent = void 0;
37
+ const path = __importStar(require("path"));
38
+ const FileSystemUtils_1 = require("../core/FileSystemUtils");
39
+ /**
40
+ * Cline agent adapter (stub implementation).
41
+ */
42
+ class ClineAgent {
43
+ getName() {
44
+ return 'Cline';
45
+ }
46
+ async applyRulerConfig(concatenatedRules, projectRoot) {
47
+ const target = path.join(projectRoot, '.clinerules');
48
+ await (0, FileSystemUtils_1.backupFile)(target);
49
+ await (0, FileSystemUtils_1.writeGeneratedFile)(target, concatenatedRules);
50
+ }
51
+ }
52
+ exports.ClineAgent = ClineAgent;
@@ -0,0 +1,52 @@
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.CodexCliAgent = void 0;
37
+ const path = __importStar(require("path"));
38
+ const FileSystemUtils_1 = require("../core/FileSystemUtils");
39
+ /**
40
+ * OpenAI Codex CLI agent adapter (stub implementation).
41
+ */
42
+ class CodexCliAgent {
43
+ getName() {
44
+ return 'OpenAI Codex CLI';
45
+ }
46
+ async applyRulerConfig(concatenatedRules, projectRoot) {
47
+ const target = path.join(projectRoot, 'AGENTS.md');
48
+ await (0, FileSystemUtils_1.backupFile)(target);
49
+ await (0, FileSystemUtils_1.writeGeneratedFile)(target, concatenatedRules);
50
+ }
51
+ }
52
+ exports.CodexCliAgent = CodexCliAgent;
@@ -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.CopilotAgent = void 0;
37
+ const path = __importStar(require("path"));
38
+ const FileSystemUtils_1 = require("../core/FileSystemUtils");
39
+ /**
40
+ * GitHub Copilot agent adapter (stub implementation).
41
+ */
42
+ class CopilotAgent {
43
+ getName() {
44
+ return 'GitHub Copilot';
45
+ }
46
+ async applyRulerConfig(concatenatedRules, projectRoot) {
47
+ const targetDir = path.join(projectRoot, '.github');
48
+ await (0, FileSystemUtils_1.ensureDirExists)(targetDir);
49
+ const target = path.join(targetDir, 'copilot-instructions.md');
50
+ await (0, FileSystemUtils_1.backupFile)(target);
51
+ await (0, FileSystemUtils_1.writeGeneratedFile)(target, concatenatedRules);
52
+ }
53
+ }
54
+ exports.CopilotAgent = CopilotAgent;
@@ -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.CursorAgent = void 0;
37
+ const path = __importStar(require("path"));
38
+ const FileSystemUtils_1 = require("../core/FileSystemUtils");
39
+ /**
40
+ * Cursor agent adapter (stub implementation).
41
+ */
42
+ class CursorAgent {
43
+ getName() {
44
+ return 'Cursor';
45
+ }
46
+ async applyRulerConfig(concatenatedRules, projectRoot) {
47
+ const targetDir = path.join(projectRoot, '.cursor', 'rules');
48
+ await (0, FileSystemUtils_1.ensureDirExists)(targetDir);
49
+ const target = path.join(targetDir, 'ruler_cursor_instructions.md');
50
+ await (0, FileSystemUtils_1.backupFile)(target);
51
+ await (0, FileSystemUtils_1.writeGeneratedFile)(target, concatenatedRules);
52
+ }
53
+ }
54
+ exports.CursorAgent = CursorAgent;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: 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.WindsurfAgent = void 0;
37
+ const path = __importStar(require("path"));
38
+ const FileSystemUtils_1 = require("../core/FileSystemUtils");
39
+ /**
40
+ * Windsurf agent adapter (stub implementation).
41
+ */
42
+ class WindsurfAgent {
43
+ getName() {
44
+ return 'Windsurf';
45
+ }
46
+ async applyRulerConfig(concatenatedRules, projectRoot) {
47
+ const targetDir = path.join(projectRoot, '.windsurf', 'rules');
48
+ await (0, FileSystemUtils_1.ensureDirExists)(targetDir);
49
+ const target = path.join(targetDir, 'ruler_windsurf_instructions.md');
50
+ await (0, FileSystemUtils_1.backupFile)(target);
51
+ await (0, FileSystemUtils_1.writeGeneratedFile)(target, concatenatedRules);
52
+ }
53
+ }
54
+ exports.WindsurfAgent = WindsurfAgent;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.run = run;
7
+ const yargs_1 = __importDefault(require("yargs"));
8
+ const helpers_1 = require("yargs/helpers");
9
+ const lib_1 = require("../lib");
10
+ /**
11
+ * Sets up and parses CLI commands.
12
+ */
13
+ function run() {
14
+ (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
15
+ .scriptName('ruler')
16
+ .usage('$0 <command> [options]')
17
+ .command('apply', 'Apply ruler configurations to supported AI agents', (y) => {
18
+ y.option('project-root', {
19
+ type: 'string',
20
+ description: 'Project root directory',
21
+ default: process.cwd(),
22
+ });
23
+ y.option('agents', {
24
+ type: 'string',
25
+ description: 'Comma-separated list of agent names to include (e.g. "copilot,claude")',
26
+ });
27
+ }, async (argv) => {
28
+ const projectRoot = argv['project-root'];
29
+ const agents = argv.agents
30
+ ? argv.agents.split(',').map((a) => a.trim())
31
+ : undefined;
32
+ try {
33
+ await (0, lib_1.applyAllAgentConfigs)(projectRoot, agents);
34
+ console.log('Ruler apply completed successfully.');
35
+ }
36
+ catch (err) {
37
+ const message = err instanceof Error ? err.message : String(err);
38
+ console.error('Error applying ruler configurations:', message);
39
+ process.exit(1);
40
+ }
41
+ })
42
+ .demandCommand(1, 'You need to specify a command')
43
+ .help()
44
+ .strict()
45
+ .parse();
46
+ }
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commands_1 = require("./commands");
5
+ (0, commands_1.run)();
@@ -0,0 +1,115 @@
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.findRulerDir = findRulerDir;
37
+ exports.readMarkdownFiles = readMarkdownFiles;
38
+ exports.writeGeneratedFile = writeGeneratedFile;
39
+ exports.backupFile = backupFile;
40
+ exports.ensureDirExists = ensureDirExists;
41
+ const fs_1 = require("fs");
42
+ const path = __importStar(require("path"));
43
+ /**
44
+ * Searches upwards from startPath to find a directory named .ruler.
45
+ * Returns the path to the .ruler directory, or null if not found.
46
+ */
47
+ async function findRulerDir(startPath) {
48
+ let current = startPath;
49
+ while (current) {
50
+ const candidate = path.join(current, '.ruler');
51
+ try {
52
+ const stat = await fs_1.promises.stat(candidate);
53
+ if (stat.isDirectory()) {
54
+ return candidate;
55
+ }
56
+ }
57
+ catch {
58
+ // ignore errors when checking for .ruler directory
59
+ }
60
+ const parent = path.dirname(current);
61
+ if (parent === current) {
62
+ break;
63
+ }
64
+ current = parent;
65
+ }
66
+ return null;
67
+ }
68
+ /**
69
+ * Recursively reads all Markdown (.md) files in rulerDir, returning their paths and contents.
70
+ * Files are sorted alphabetically by path.
71
+ */
72
+ async function readMarkdownFiles(rulerDir) {
73
+ const results = [];
74
+ async function walk(dir) {
75
+ const entries = await fs_1.promises.readdir(dir, { withFileTypes: true });
76
+ for (const entry of entries) {
77
+ const fullPath = path.join(dir, entry.name);
78
+ if (entry.isDirectory()) {
79
+ await walk(fullPath);
80
+ }
81
+ else if (entry.isFile() && entry.name.endsWith('.md')) {
82
+ const content = await fs_1.promises.readFile(fullPath, 'utf8');
83
+ results.push({ path: fullPath, content });
84
+ }
85
+ }
86
+ }
87
+ await walk(rulerDir);
88
+ results.sort((a, b) => a.path.localeCompare(b.path));
89
+ return results;
90
+ }
91
+ /**
92
+ * Writes content to filePath, creating parent directories if necessary.
93
+ */
94
+ async function writeGeneratedFile(filePath, content) {
95
+ await fs_1.promises.mkdir(path.dirname(filePath), { recursive: true });
96
+ await fs_1.promises.writeFile(filePath, content, 'utf8');
97
+ }
98
+ /**
99
+ * Creates a backup of the given filePath by copying it to filePath.bak if it exists.
100
+ */
101
+ async function backupFile(filePath) {
102
+ try {
103
+ await fs_1.promises.access(filePath);
104
+ await fs_1.promises.copyFile(filePath, `${filePath}.bak`);
105
+ }
106
+ catch {
107
+ // ignore if file does not exist
108
+ }
109
+ }
110
+ /**
111
+ * Ensures that the given directory exists by creating it recursively.
112
+ */
113
+ async function ensureDirExists(dirPath) {
114
+ await fs_1.promises.mkdir(dirPath, { recursive: true });
115
+ }
@@ -0,0 +1,48 @@
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.concatenateRules = concatenateRules;
37
+ const path = __importStar(require("path"));
38
+ /**
39
+ * Concatenates markdown rule files into a single string,
40
+ * marking each section with its source filename.
41
+ */
42
+ function concatenateRules(files) {
43
+ const sections = files.map(({ path: filePath, content }) => {
44
+ const rel = path.relative(process.cwd(), filePath);
45
+ return ['---', `Source: ${rel}`, '---', content.trim(), ''].join('\n');
46
+ });
47
+ return sections.join('\n');
48
+ }
package/dist/lib.js ADDED
@@ -0,0 +1,82 @@
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.applyAllAgentConfigs = applyAllAgentConfigs;
37
+ const path = __importStar(require("path"));
38
+ const FileSystemUtils_1 = require("./core/FileSystemUtils");
39
+ const RuleProcessor_1 = require("./core/RuleProcessor");
40
+ const CopilotAgent_1 = require("./agents/CopilotAgent");
41
+ const ClaudeAgent_1 = require("./agents/ClaudeAgent");
42
+ const CodexCliAgent_1 = require("./agents/CodexCliAgent");
43
+ const CursorAgent_1 = require("./agents/CursorAgent");
44
+ const WindsurfAgent_1 = require("./agents/WindsurfAgent");
45
+ const ClineAgent_1 = require("./agents/ClineAgent");
46
+ const AiderAgent_1 = require("./agents/AiderAgent");
47
+ const agents = [
48
+ new CopilotAgent_1.CopilotAgent(),
49
+ new ClaudeAgent_1.ClaudeAgent(),
50
+ new CodexCliAgent_1.CodexCliAgent(),
51
+ new CursorAgent_1.CursorAgent(),
52
+ new WindsurfAgent_1.WindsurfAgent(),
53
+ new ClineAgent_1.ClineAgent(),
54
+ new AiderAgent_1.AiderAgent(),
55
+ ];
56
+ /**
57
+ * Applies ruler configurations for all supported AI agents.
58
+ * @param projectRoot Root directory of the project
59
+ */
60
+ /**
61
+ * Applies ruler configurations for selected AI agents.
62
+ * @param projectRoot Root directory of the project
63
+ * @param includedAgents Optional list of agent name filters (case-insensitive substrings)
64
+ */
65
+ async function applyAllAgentConfigs(projectRoot, includedAgents) {
66
+ const rulerDir = await (0, FileSystemUtils_1.findRulerDir)(projectRoot);
67
+ if (!rulerDir) {
68
+ throw new Error(`.ruler directory not found from ${projectRoot}`);
69
+ }
70
+ await (0, FileSystemUtils_1.ensureDirExists)(path.join(rulerDir, 'generated'));
71
+ const files = await (0, FileSystemUtils_1.readMarkdownFiles)(rulerDir);
72
+ const concatenated = (0, RuleProcessor_1.concatenateRules)(files);
73
+ let selected = agents;
74
+ if (includedAgents && includedAgents.length > 0) {
75
+ const filters = includedAgents.map((n) => n.toLowerCase());
76
+ selected = agents.filter((agent) => filters.some((f) => agent.getName().toLowerCase().includes(f)));
77
+ }
78
+ for (const agent of selected) {
79
+ console.log(`[ruler] Applying rules for ${agent.getName()}...`);
80
+ await agent.applyRulerConfig(concatenated, projectRoot);
81
+ }
82
+ }
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@intellectronica/ruler",
3
+ "version": "0.1.0",
4
+ "description": "",
5
+ "main": "dist/lib.js",
6
+ "scripts": {
7
+ "lint": "eslint \"src/**/*.{ts,tsx}\"",
8
+ "format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
9
+ "test": "jest",
10
+ "test:watch": "jest --watch",
11
+ "build": "tsc",
12
+ "prepare": "npm run build"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/intellectronica/ruler.git"
17
+ },
18
+ "keywords": [
19
+ "ai",
20
+ "developer-tools",
21
+ "copilot",
22
+ "codex",
23
+ "claude",
24
+ "cursor",
25
+ "aider",
26
+ "config",
27
+ "rules",
28
+ "automation"
29
+ ],
30
+ "author": "Eleanor Berger",
31
+ "license": "MIT",
32
+ "bugs": {
33
+ "url": "https://github.com/intellectronica/ruler/issues"
34
+ },
35
+ "homepage": "https://github.com/intellectronica/ruler#readme",
36
+ "files": [
37
+ "dist",
38
+ "README.md",
39
+ "LICENSE"
40
+ ],
41
+ "bin": {
42
+ "ruler": "dist/cli/index.js"
43
+ },
44
+ "devDependencies": {
45
+ "@types/jest": "^29.5.14",
46
+ "@types/js-yaml": "^4.0.9",
47
+ "@types/yargs": "^17.0.33",
48
+ "@typescript-eslint/eslint-plugin": "^8.32.1",
49
+ "@typescript-eslint/parser": "^8.32.1",
50
+ "eslint": "^8.57.1",
51
+ "eslint-config-prettier": "^10.1.5",
52
+ "eslint-plugin-prettier": "^5.4.0",
53
+ "jest": "^29.7.0",
54
+ "prettier": "^3.5.3",
55
+ "ts-jest": "^29.3.4",
56
+ "typescript": "^5.8.3",
57
+ "yargs": "^17.7.2"
58
+ },
59
+ "dependencies": {
60
+ "js-yaml": "^4.1.0"
61
+ }
62
+ }