rulesync 0.4.0 → 0.5.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/README.md CHANGED
@@ -8,9 +8,9 @@ A Node.js CLI tool that automatically generates configuration files for various
8
8
  ## Supported Tools
9
9
 
10
10
  - **GitHub Copilot Custom Instructions** (`.github/instructions/*.instructions.md`)
11
- - **Cursor Project Rules** (`.cursor/rules/*.md`)
11
+ - **Cursor Project Rules** (`.cursor/rules/*.mdc`)
12
12
  - **Cline Rules** (`.clinerules/*.md`)
13
- - **Claude Code Memory** (`./CLAUDE.md`)
13
+ - **Claude Code Memory** (`./CLAUDE.md` + `.claude/memories/*.md`)
14
14
 
15
15
  ## Installation
16
16
 
@@ -22,6 +22,132 @@ pnpm add -g rulesync
22
22
  yarn global add rulesync
23
23
  ```
24
24
 
25
+ ## Getting Started
26
+
27
+ ### Quick Start Example
28
+
29
+ 1. **Initialize your project:**
30
+ ```bash
31
+ rulesync init
32
+ ```
33
+
34
+ 2. **Create an overview file** (`.rulesync/overview.md`):
35
+ ```markdown
36
+ ---
37
+ root: true
38
+ targets: ["*"]
39
+ description: "Project overview and development philosophy"
40
+ globs: ["src/**/*.ts", "src/**/*.js"]
41
+ ---
42
+
43
+ # Project Development Guidelines
44
+
45
+ This is a TypeScript/JavaScript project following clean architecture principles.
46
+ We prioritize code readability, maintainability, and type safety.
47
+
48
+ ## Tech Stack
49
+ - TypeScript for type safety
50
+ - Node.js runtime
51
+ - Modern ES6+ features
52
+ ```
53
+
54
+ 3. **Create detail rules** (`.rulesync/coding-rules.md`):
55
+ ```markdown
56
+ ---
57
+ root: false
58
+ targets: ["copilot", "cursor", "cline"]
59
+ description: "TypeScript coding standards and best practices"
60
+ globs: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"]
61
+ ---
62
+
63
+ # TypeScript Coding Rules
64
+
65
+ ## Code Style
66
+ - Use strict TypeScript configuration
67
+ - Prefer `const` over `let` when possible
68
+ - Use meaningful, descriptive variable names
69
+ - Write JSDoc comments for public APIs
70
+
71
+ ## Type Definitions
72
+ - Prefer interfaces over types for object shapes
73
+ - Use union types for controlled values
74
+ - Avoid `any` type - use `unknown` instead
75
+ - Define return types for functions explicitly
76
+
77
+ ## Error Handling
78
+ - Use Result pattern for error handling
79
+ - Throw errors only for unexpected conditions
80
+ - Validate input parameters at function boundaries
81
+ ```
82
+
83
+ 4. **Generate configuration files:**
84
+ ```bash
85
+ rulesync generate
86
+ ```
87
+
88
+ 5. **Optional: Add generated files to .gitignore:**
89
+ ```bash
90
+ rulesync gitignore
91
+ ```
92
+
93
+ This will create tool-specific configuration files that your AI coding assistants can use automatically.
94
+
95
+ ## Why rulesync?
96
+
97
+ ### 🔧 **Tool Flexibility**
98
+ Team members can freely choose their preferred AI coding tools. Whether it's GitHub Copilot, Cursor, Cline, or Claude Code, each developer can use the tool that maximizes their productivity.
99
+
100
+ ### 📈 **Future-Proof Development**
101
+ AI development tools evolve rapidly with new tools emerging frequently. With rulesync, switching between tools doesn't require redefining your rules from scratch.
102
+
103
+ ### 🎯 **Multi-Tool Workflow**
104
+ Enable hybrid development workflows combining multiple AI tools:
105
+ - GitHub Copilot for code completion
106
+ - Cursor for refactoring
107
+ - Claude Code for architecture design
108
+ - Cline for debugging assistance
109
+
110
+ ### 🔓 **No Vendor Lock-in**
111
+ Avoid vendor lock-in completely. If you decide to stop using rulesync, you can continue using the generated rule files (`.github/instructions/`, `.cursor/rules/`, `.clinerules/`, `CLAUDE.md`, etc.) as-is.
112
+
113
+ ### 🎯 **Consistency Across Tools**
114
+ Apply consistent rules across all AI tools, improving code quality and development experience for the entire team.
115
+
116
+ ## Claude Code Integration
117
+
118
+ ### Creating Custom Slash Commands
119
+
120
+ Instead of using Claude Code's built-in `/init` command, we recommend creating a custom slash command specifically for rulesync.
121
+
122
+ Refer to the [Claude Code slash commands documentation](https://docs.anthropic.com/en/docs/claude-code/slash-commands) and add the following custom command:
123
+
124
+ **`.claude/commands/init-rulesync.md`**
125
+
126
+ ```markdown
127
+ Review this project's content and update .rulesync/*.md files as needed.
128
+
129
+ Steps:
130
+ 1. Analyze project structure and codebase
131
+ 2. Review existing .rulesync/ files
132
+ 3. Consider project's tech stack, architecture, and coding conventions
133
+ 4. Update .rulesync/*.md files if missing elements or improvements are found
134
+ 5. Run rulesync generate if necessary
135
+
136
+ Project characteristics to consider:
137
+ - Technology stack
138
+ - Architecture patterns
139
+ - Coding conventions
140
+ - Security requirements
141
+ - Performance considerations
142
+ ```
143
+
144
+ ### Integration Benefits
145
+
146
+ - **Project-Specific Initialization**: Optimized rule configuration for each project
147
+ - **Automatic Rule Updates**: Rules adapt to project changes automatically
148
+ - **Team Standardization**: All members use the same rule set
149
+ - **Continuous Improvement**: Rules evolve with project growth
150
+
25
151
  ## Usage
26
152
 
27
153
  ### 1. Initialize
@@ -38,7 +164,7 @@ Define metadata in front matter for each Markdown file:
38
164
 
39
165
  ```markdown
40
166
  ---
41
- ruleLevel: overview # or detail
167
+ root: true # or false
42
168
  targets: ["*"] # or [copilot, cursor, cline, claudecode]
43
169
  description: "TypeScript coding rules"
44
170
  globs: ["**/*.ts", "**/*.tsx"]
@@ -52,12 +178,25 @@ globs: ["**/*.ts", "**/*.tsx"]
52
178
 
53
179
  ### Rule Levels
54
180
 
55
- - **overview**: Project-wide overview and policies (only one file allowed)
56
- - **detail**: Specific implementation rules and detailed guidelines (multiple files allowed)
181
+ rulesync uses a two-level rule system:
182
+
183
+ - **root: true**: Project-wide overview and policies
184
+ - Only **one** root file is allowed per project
185
+ - Contains high-level guidelines and project context
186
+ - **root: false**: Specific implementation rules and detailed guidelines
187
+ - Multiple non-root files are allowed
188
+ - Contains specific coding rules, naming conventions, etc.
189
+
190
+ #### Tool-Specific Behavior
191
+
192
+ Each AI tool handles rule levels differently:
57
193
 
58
- Each tool handles rule levels differently:
59
- - **Claude Code**: overview → `CLAUDE.md`, detail → `.claude/memories/*.md`
60
- - **Cursor**: overview `ruletype: always`, detail `ruletype: autoattached`
194
+ | Tool | Root Rules | Non-Root Rules | Special Behavior |
195
+ |------|------------|----------------|------------------|
196
+ | **Claude Code** | `./CLAUDE.md` | `.claude/memories/*.md` | CLAUDE.md includes `@filename` references to detail files |
197
+ | **Cursor** | `ruletype: always` | `ruletype: autoattached` | Detail rules without globs use `ruletype: agentrequested` |
198
+ | **GitHub Copilot** | Standard format | Standard format | All rules use same format with frontmatter |
199
+ | **Cline** | Standard format | Standard format | All rules use plain Markdown format |
61
200
 
62
201
  ### 3. Generate Configuration Files
63
202
 
@@ -70,62 +209,123 @@ rulesync generate --copilot
70
209
  rulesync generate --cursor
71
210
  rulesync generate --cline
72
211
  rulesync generate --claude
212
+
213
+ # Clean build (delete existing files first)
214
+ rulesync generate --delete
215
+
216
+ # Clean build for specific tools
217
+ rulesync generate --copilot --cursor --delete
218
+
219
+ # Verbose output
220
+ rulesync generate --verbose
221
+ rulesync generate --delete --verbose
73
222
  ```
74
223
 
224
+ #### Generate Options
225
+
226
+ - `--delete`: Remove all existing generated files before creating new ones
227
+ - `--verbose`: Show detailed output during generation process
228
+ - `--copilot`, `--cursor`, `--cline`, `--claude`: Generate only for specified tools
229
+
75
230
  ### 4. Other Commands
76
231
 
77
232
  ```bash
78
- # Validate configuration
233
+ # Initialize project with sample files
234
+ rulesync init
235
+
236
+ # Validate rule files
79
237
  rulesync validate
80
238
 
81
- # Check current status
239
+ # Check current status
82
240
  rulesync status
83
241
 
84
242
  # Watch files and auto-generate
85
243
  rulesync watch
244
+
245
+ # Add generated files to .gitignore
246
+ rulesync gitignore
86
247
  ```
87
248
 
88
249
  ## Configuration File Structure
89
250
 
90
251
  ```
91
252
  .rulesync/
92
- ├── coding-rules.md # Coding rules
93
- ├── naming-conventions.md # Naming conventions
94
- ├── architecture.md # Architecture guidelines
95
- ├── security.md # Security rules
96
- └── custom.md # Project-specific rules
253
+ ├── overview.md # Project overview (root: true, only one)
254
+ ├── coding-rules.md # Coding rules (root: false)
255
+ ├── naming-conventions.md # Naming conventions (root: false)
256
+ ├── architecture.md # Architecture guidelines (root: false)
257
+ ├── security.md # Security rules (root: false)
258
+ └── custom.md # Project-specific rules (root: false)
97
259
  ```
98
260
 
99
- ## Generated Configuration Files
261
+ ### Frontmatter Schema
100
262
 
101
- | Tool | Output Path | Format |
102
- |------|------------|--------|
103
- | GitHub Copilot | `.github/instructions/*.instructions.md` | Front Matter + Markdown |
104
- | Cursor | `.cursor/rules/*.md` | MDC (YAML header + Markdown) |
105
- | Cline | `.clinerules/*.md` | Plain Markdown |
106
- | Claude Code | `./CLAUDE.md` (overview), `.claude/memories/*.md` (detail) | Plain Markdown |
263
+ Each rule file must include frontmatter with the following fields:
107
264
 
108
- ## Development
265
+ ```yaml
266
+ ---
267
+ root: true | false # Required: Rule level (true for overview, false for details)
268
+ targets: ["*"] # Required: Target tools (* = all, or specific tools)
269
+ description: "Brief description" # Required: Rule description
270
+ globs: ["**/*.ts", "**/*.js"] # Required: File patterns (can be empty array)
271
+ ---
272
+ ```
109
273
 
110
- ```bash
111
- # Install dependencies
112
- pnpm install
274
+ ### Example Files
113
275
 
114
- # Development run
115
- pnpm dev
276
+ **Root file** (`.rulesync/overview.md`):
277
+ ```markdown
278
+ ---
279
+ root: true
280
+ targets: ["*"]
281
+ description: "Project overview and development philosophy"
282
+ globs: ["src/**/*.ts"]
283
+ ---
116
284
 
117
- # Build
118
- pnpm build
285
+ # Project Development Guidelines
119
286
 
120
- # Test
121
- pnpm test
287
+ This project follows TypeScript-first development with clean architecture principles.
288
+ ```
122
289
 
123
- # Code quality checks
124
- pnpm lint
125
- pnpm format
126
- pnpm secretlint
290
+ **Non-root file** (`.rulesync/coding-rules.md`):
291
+ ```markdown
292
+ ---
293
+ root: false
294
+ targets: ["copilot", "cursor"]
295
+ description: "TypeScript coding standards"
296
+ globs: ["**/*.ts", "**/*.tsx"]
297
+ ---
298
+
299
+ # TypeScript Coding Rules
300
+
301
+ - Use strict TypeScript configuration
302
+ - Prefer interfaces over types for object shapes
303
+ - Use meaningful variable names
304
+ ```
305
+
306
+ ## Generated Configuration Files
307
+
308
+ | Tool | Output Path | Format | Rule Level Handling |
309
+ |------|------------|--------|-------------------|
310
+ | **GitHub Copilot** | `.github/instructions/*.instructions.md` | Front Matter + Markdown | Both levels use same format |
311
+ | **Cursor** | `.cursor/rules/*.mdc` | MDC (YAML header + Markdown) | Root: `ruletype: always`<br>Non-root: `ruletype: autoattached`<br>Non-root without globs: `ruletype: agentrequested` |
312
+ | **Cline** | `.clinerules/*.md` | Plain Markdown | Both levels use same format |
313
+ | **Claude Code** | `./CLAUDE.md` (root)<br>`.claude/memories/*.md` (non-root) | Plain Markdown | Root goes to CLAUDE.md<br>Non-root go to separate memory files<br>CLAUDE.md includes `@filename` references |
314
+
315
+ ## Validation
316
+
317
+ rulesync validates your rule files and provides helpful error messages:
318
+
319
+ ```bash
320
+ rulesync validate
127
321
  ```
128
322
 
323
+ Common validation rules:
324
+ - Only one root file (root: true) is allowed per project
325
+ - All frontmatter fields are required and properly formatted
326
+ - File patterns (globs) use valid syntax
327
+ - Target tools are recognized values
328
+
129
329
  ## License
130
330
 
131
331
  MIT License
@@ -134,4 +334,4 @@ MIT License
134
334
 
135
335
  Issues and Pull Requests are welcome!
136
336
 
137
- For detailed specifications, see [SPECIFICATION.md](./SPECIFICATION.md).
337
+ For development setup and contribution guidelines, see [CONTRIBUTING.md](./CONTRIBUTING.md).
package/dist/index.js CHANGED
@@ -30,9 +30,9 @@ var import_commander = require("commander");
30
30
  var import_node_path = require("path");
31
31
  async function generateClaudeConfig(rules, config) {
32
32
  const outputs = [];
33
- const overviewRules = rules.filter((r) => r.frontmatter.ruleLevel === "overview");
34
- const detailRules = rules.filter((r) => r.frontmatter.ruleLevel === "detail");
35
- const claudeMdContent = generateClaudeMarkdown(overviewRules, detailRules);
33
+ const rootRules = rules.filter((r) => r.frontmatter.root === true);
34
+ const detailRules = rules.filter((r) => r.frontmatter.root === false);
35
+ const claudeMdContent = generateClaudeMarkdown(rootRules, detailRules);
36
36
  outputs.push({
37
37
  tool: "claude",
38
38
  filepath: (0, import_node_path.join)(config.outputPaths.claude, "CLAUDE.md"),
@@ -48,7 +48,7 @@ async function generateClaudeConfig(rules, config) {
48
48
  }
49
49
  return outputs;
50
50
  }
51
- function generateClaudeMarkdown(overviewRules, detailRules) {
51
+ function generateClaudeMarkdown(rootRules, detailRules) {
52
52
  const lines = [];
53
53
  if (detailRules.length > 0) {
54
54
  for (const rule of detailRules) {
@@ -62,8 +62,8 @@ function generateClaudeMarkdown(overviewRules, detailRules) {
62
62
  "Generated from rulesync configuration. These instructions guide Claude Code's behavior for this project."
63
63
  );
64
64
  lines.push("");
65
- if (overviewRules.length > 0) {
66
- for (const rule of overviewRules) {
65
+ if (rootRules.length > 0) {
66
+ for (const rule of rootRules) {
67
67
  lines.push(...formatRuleForClaude(rule));
68
68
  }
69
69
  }
@@ -169,7 +169,7 @@ async function generateCursorConfig(rules, config) {
169
169
  const outputs = [];
170
170
  for (const rule of rules) {
171
171
  const content = generateCursorMarkdown(rule);
172
- const filepath = (0, import_node_path4.join)(config.outputPaths.cursor, `${rule.filename}.md`);
172
+ const filepath = (0, import_node_path4.join)(config.outputPaths.cursor, `${rule.filename}.mdc`);
173
173
  outputs.push({
174
174
  tool: "cursor",
175
175
  filepath,
@@ -186,9 +186,9 @@ function generateCursorMarkdown(rule) {
186
186
  lines.push(`globs: [${rule.frontmatter.globs.map((g) => `"${g}"`).join(", ")}]`);
187
187
  }
188
188
  let ruletype;
189
- if (rule.frontmatter.ruleLevel === "overview") {
189
+ if (rule.frontmatter.root === true) {
190
190
  ruletype = "always";
191
- } else if (rule.frontmatter.ruleLevel === "detail" && rule.frontmatter.globs.length === 0) {
191
+ } else if (rule.frontmatter.root === false && rule.frontmatter.globs.length === 0) {
192
192
  ruletype = "agentrequested";
193
193
  } else {
194
194
  ruletype = "autoattached";
@@ -337,8 +337,8 @@ function validateFrontmatter(data, filepath) {
337
337
  throw new Error(`Invalid frontmatter in ${filepath}: must be an object`);
338
338
  }
339
339
  const obj = data;
340
- if (!obj.ruleLevel || !["overview", "detail"].includes(obj.ruleLevel)) {
341
- throw new Error(`Invalid ruleLevel in ${filepath}: must be "overview" or "detail"`);
340
+ if (typeof obj.root !== "boolean") {
341
+ throw new Error(`Invalid root in ${filepath}: must be a boolean`);
342
342
  }
343
343
  if (!Array.isArray(obj.targets)) {
344
344
  throw new Error(`Invalid targets in ${filepath}: must be an array`);
@@ -375,9 +375,11 @@ async function validateRules(rules) {
375
375
  }
376
376
  filenames.add(rule.filename);
377
377
  }
378
- const overviewRules = rules.filter((rule) => rule.frontmatter.ruleLevel === "overview");
379
- if (overviewRules.length > 1) {
380
- errors.push(`Multiple overview rules found: ${overviewRules.map((r) => r.filename).join(", ")}. Only one overview rule is allowed.`);
378
+ const rootRules = rules.filter((rule) => rule.frontmatter.root === true);
379
+ if (rootRules.length > 1) {
380
+ errors.push(
381
+ `Multiple root rules found: ${rootRules.map((r) => r.filename).join(", ")}. Only one root rule is allowed.`
382
+ );
381
383
  }
382
384
  for (const rule of rules) {
383
385
  const ruleValidation = await validateRule(rule);
package/dist/index.mjs CHANGED
@@ -7,9 +7,9 @@ import { Command } from "commander";
7
7
  import { join } from "path";
8
8
  async function generateClaudeConfig(rules, config) {
9
9
  const outputs = [];
10
- const overviewRules = rules.filter((r) => r.frontmatter.ruleLevel === "overview");
11
- const detailRules = rules.filter((r) => r.frontmatter.ruleLevel === "detail");
12
- const claudeMdContent = generateClaudeMarkdown(overviewRules, detailRules);
10
+ const rootRules = rules.filter((r) => r.frontmatter.root === true);
11
+ const detailRules = rules.filter((r) => r.frontmatter.root === false);
12
+ const claudeMdContent = generateClaudeMarkdown(rootRules, detailRules);
13
13
  outputs.push({
14
14
  tool: "claude",
15
15
  filepath: join(config.outputPaths.claude, "CLAUDE.md"),
@@ -25,7 +25,7 @@ async function generateClaudeConfig(rules, config) {
25
25
  }
26
26
  return outputs;
27
27
  }
28
- function generateClaudeMarkdown(overviewRules, detailRules) {
28
+ function generateClaudeMarkdown(rootRules, detailRules) {
29
29
  const lines = [];
30
30
  if (detailRules.length > 0) {
31
31
  for (const rule of detailRules) {
@@ -39,8 +39,8 @@ function generateClaudeMarkdown(overviewRules, detailRules) {
39
39
  "Generated from rulesync configuration. These instructions guide Claude Code's behavior for this project."
40
40
  );
41
41
  lines.push("");
42
- if (overviewRules.length > 0) {
43
- for (const rule of overviewRules) {
42
+ if (rootRules.length > 0) {
43
+ for (const rule of rootRules) {
44
44
  lines.push(...formatRuleForClaude(rule));
45
45
  }
46
46
  }
@@ -146,7 +146,7 @@ async function generateCursorConfig(rules, config) {
146
146
  const outputs = [];
147
147
  for (const rule of rules) {
148
148
  const content = generateCursorMarkdown(rule);
149
- const filepath = join4(config.outputPaths.cursor, `${rule.filename}.md`);
149
+ const filepath = join4(config.outputPaths.cursor, `${rule.filename}.mdc`);
150
150
  outputs.push({
151
151
  tool: "cursor",
152
152
  filepath,
@@ -163,9 +163,9 @@ function generateCursorMarkdown(rule) {
163
163
  lines.push(`globs: [${rule.frontmatter.globs.map((g) => `"${g}"`).join(", ")}]`);
164
164
  }
165
165
  let ruletype;
166
- if (rule.frontmatter.ruleLevel === "overview") {
166
+ if (rule.frontmatter.root === true) {
167
167
  ruletype = "always";
168
- } else if (rule.frontmatter.ruleLevel === "detail" && rule.frontmatter.globs.length === 0) {
168
+ } else if (rule.frontmatter.root === false && rule.frontmatter.globs.length === 0) {
169
169
  ruletype = "agentrequested";
170
170
  } else {
171
171
  ruletype = "autoattached";
@@ -314,8 +314,8 @@ function validateFrontmatter(data, filepath) {
314
314
  throw new Error(`Invalid frontmatter in ${filepath}: must be an object`);
315
315
  }
316
316
  const obj = data;
317
- if (!obj.ruleLevel || !["overview", "detail"].includes(obj.ruleLevel)) {
318
- throw new Error(`Invalid ruleLevel in ${filepath}: must be "overview" or "detail"`);
317
+ if (typeof obj.root !== "boolean") {
318
+ throw new Error(`Invalid root in ${filepath}: must be a boolean`);
319
319
  }
320
320
  if (!Array.isArray(obj.targets)) {
321
321
  throw new Error(`Invalid targets in ${filepath}: must be an array`);
@@ -352,9 +352,11 @@ async function validateRules(rules) {
352
352
  }
353
353
  filenames.add(rule.filename);
354
354
  }
355
- const overviewRules = rules.filter((rule) => rule.frontmatter.ruleLevel === "overview");
356
- if (overviewRules.length > 1) {
357
- errors.push(`Multiple overview rules found: ${overviewRules.map((r) => r.filename).join(", ")}. Only one overview rule is allowed.`);
355
+ const rootRules = rules.filter((rule) => rule.frontmatter.root === true);
356
+ if (rootRules.length > 1) {
357
+ errors.push(
358
+ `Multiple root rules found: ${rootRules.map((r) => r.filename).join(", ")}. Only one root rule is allowed.`
359
+ );
358
360
  }
359
361
  for (const rule of rules) {
360
362
  const ruleValidation = await validateRule(rule);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rulesync",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Unified AI rules management CLI tool that generates configuration files for various AI development tools",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",