@intellectronica/ruler 0.3.34 → 0.3.35

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
@@ -238,6 +238,7 @@ The `apply` command looks for `.ruler/` in the current directory tree, reading t
238
238
  | `--mcp-overwrite` | Overwrite native MCP config instead of merging. |
239
239
  | `--gitignore` | Enable automatic .gitignore updates (default: true). |
240
240
  | `--no-gitignore` | Disable automatic .gitignore updates. |
241
+ | `--gitignore-local` | Write managed ignore entries to `.git/info/exclude` instead. |
241
242
  | `--nested` | Enable nested rule loading (default: inherit from config or disabled). |
242
243
  | `--no-nested` | Disable nested rule loading even if `nested = true` in config. |
243
244
  | `--backup` | Toggle creation of `.bak` backup files (default: enabled). |
@@ -405,6 +406,8 @@ Authorization = "Bearer your-token"
405
406
  [gitignore]
406
407
  # Enable/disable automatic .gitignore updates (default: true)
407
408
  enabled = true
409
+ # Write managed entries to .git/info/exclude instead of .gitignore (default: false)
410
+ local = false
408
411
 
409
412
  # --- Agent-Specific Configurations ---
410
413
  [agents.copilot]
@@ -744,8 +747,8 @@ dist/
744
747
 
745
748
  ### Control Options
746
749
 
747
- - **CLI flags**: `--gitignore` or `--no-gitignore`
748
- - **Configuration**: `[gitignore].enabled` in `ruler.toml`
750
+ - **CLI flags**: `--gitignore`, `--no-gitignore`, `--gitignore-local`, `--no-gitignore-local`
751
+ - **Configuration**: `[gitignore].enabled` and `[gitignore].local` in `ruler.toml`
749
752
  - **Default**: enabled
750
753
 
751
754
  ## Practical Usage Scenarios
@@ -44,6 +44,10 @@ function run() {
44
44
  .option('gitignore', {
45
45
  type: 'boolean',
46
46
  description: 'Enable/disable automatic .gitignore updates (default: enabled)',
47
+ })
48
+ .option('gitignore-local', {
49
+ type: 'boolean',
50
+ description: 'Write generated ignore entries to .git/info/exclude instead of .gitignore',
47
51
  })
48
52
  .option('verbose', {
49
53
  type: 'boolean',
@@ -78,6 +78,13 @@ async function applyHandler(argv) {
78
78
  else {
79
79
  gitignorePreference = undefined; // Let TOML/default decide
80
80
  }
81
+ let gitignoreLocalPreference;
82
+ if (argv['gitignore-local'] !== undefined) {
83
+ gitignoreLocalPreference = argv['gitignore-local'];
84
+ }
85
+ else {
86
+ gitignoreLocalPreference = undefined; // Let TOML/default decide
87
+ }
81
88
  // Determine nested preference: CLI > TOML > Default (false)
82
89
  let nested;
83
90
  if (argv.nested !== undefined) {
@@ -108,7 +115,7 @@ async function applyHandler(argv) {
108
115
  skillsEnabled = undefined; // Let config/default decide
109
116
  }
110
117
  try {
111
- await (0, lib_1.applyAllAgentConfigs)(projectRoot, agents, configPath, mcpEnabled, mcpStrategy, gitignorePreference, verbose, dryRun, localOnly, nested, backup, skillsEnabled);
118
+ await (0, lib_1.applyAllAgentConfigs)(projectRoot, agents, configPath, mcpEnabled, mcpStrategy, gitignorePreference, verbose, dryRun, localOnly, nested, backup, skillsEnabled, gitignoreLocalPreference);
112
119
  console.log('Ruler apply completed successfully.');
113
120
  }
114
121
  catch (err) {
@@ -150,6 +157,10 @@ async function initHandler(argv) {
150
157
  # When enabled, ruler will search for and process .ruler directories throughout the project hierarchy
151
158
  # nested = false
152
159
 
160
+ # [gitignore]
161
+ # enabled = true
162
+ # local = false # set true to write generated ignores to .git/info/exclude instead
163
+
153
164
  # --- Agent Specific Configurations ---
154
165
  # You can enable/disable agents and override their default output paths here.
155
166
  # Use lowercase agent identifiers: aider, amp, claude, cline, codex, copilot, cursor, jetbrains-ai, kilocode, pi, windsurf
@@ -67,6 +67,7 @@ const rulerConfigSchema = zod_1.z.object({
67
67
  gitignore: zod_1.z
68
68
  .object({
69
69
  enabled: zod_1.z.boolean().optional(),
70
+ local: zod_1.z.boolean().optional(),
70
71
  })
71
72
  .optional(),
72
73
  skills: zod_1.z
@@ -203,6 +204,9 @@ async function loadConfig(options) {
203
204
  if (typeof rawGitignoreSection.enabled === 'boolean') {
204
205
  gitignoreConfig.enabled = rawGitignoreSection.enabled;
205
206
  }
207
+ if (typeof rawGitignoreSection.local === 'boolean') {
208
+ gitignoreConfig.local = rawGitignoreSection.local;
209
+ }
206
210
  const rawSkillsSection = raw.skills && typeof raw.skills === 'object' && !Array.isArray(raw.skills)
207
211
  ? raw.skills
208
212
  : {};
@@ -39,14 +39,15 @@ const path = __importStar(require("path"));
39
39
  const RULER_START_MARKER = '# START Ruler Generated Files';
40
40
  const RULER_END_MARKER = '# END Ruler Generated Files';
41
41
  /**
42
- * Updates the .gitignore file in the project root with paths in a managed Ruler block.
42
+ * Updates an ignore file in the project root with paths in a managed Ruler block.
43
43
  * Creates the file if it doesn't exist, and creates or updates the Ruler-managed block.
44
44
  *
45
- * @param projectRoot The project root directory (where .gitignore should be located)
46
- * @param paths Array of file paths to add to .gitignore (can be absolute or relative)
45
+ * @param projectRoot The project root directory
46
+ * @param paths Array of file paths to add to the ignore file (can be absolute or relative)
47
+ * @param ignoreFile Relative path to the ignore file from project root (defaults to .gitignore)
47
48
  */
48
- async function updateGitignore(projectRoot, paths) {
49
- const gitignorePath = path.join(projectRoot, '.gitignore');
49
+ async function updateGitignore(projectRoot, paths, ignoreFile = '.gitignore') {
50
+ const gitignorePath = path.join(projectRoot, ignoreFile);
50
51
  // Read existing .gitignore or start with empty content
51
52
  let existingContent = '';
52
53
  try {
@@ -97,6 +98,7 @@ async function updateGitignore(projectRoot, paths) {
97
98
  // Create new content
98
99
  const newContent = updateGitignoreContent(existingContent, allRulerPaths);
99
100
  // Write the updated content
101
+ await fs_1.promises.mkdir(path.dirname(gitignorePath), { recursive: true });
100
102
  await fs_1.promises.writeFile(gitignorePath, newContent);
101
103
  }
102
104
  /**
@@ -644,8 +644,9 @@ async function applyStandardMcpConfiguration(agent, filteredMcpJson, dest, agent
644
644
  * @param config Loaded configuration
645
645
  * @param cliGitignoreEnabled CLI gitignore setting
646
646
  * @param dryRun Whether to perform a dry run
647
+ * @param cliGitignoreLocal CLI toggle for .git/info/exclude usage
647
648
  */
648
- async function updateGitignore(projectRoot, generatedPaths, config, cliGitignoreEnabled, dryRun) {
649
+ async function updateGitignore(projectRoot, generatedPaths, config, cliGitignoreEnabled, dryRun, cliGitignoreLocal) {
649
650
  // Configuration precedence: CLI > TOML > Default (enabled)
650
651
  let gitignoreEnabled;
651
652
  if (cliGitignoreEnabled !== undefined) {
@@ -657,17 +658,24 @@ async function updateGitignore(projectRoot, generatedPaths, config, cliGitignore
657
658
  else {
658
659
  gitignoreEnabled = true; // Default enabled
659
660
  }
661
+ const gitignoreTarget = cliGitignoreLocal !== undefined
662
+ ? cliGitignoreLocal
663
+ ? '.git/info/exclude'
664
+ : '.gitignore'
665
+ : config.gitignore?.local
666
+ ? '.git/info/exclude'
667
+ : '.gitignore';
660
668
  if (gitignoreEnabled && generatedPaths.length > 0) {
661
669
  const uniquePaths = [...new Set(generatedPaths)];
662
670
  // Note: Individual backup patterns are added per-file in the collection phase
663
671
  // No need to add a broad *.bak pattern here
664
672
  if (uniquePaths.length > 0) {
665
673
  if (dryRun) {
666
- (0, constants_1.logInfo)(`Would update .gitignore with ${uniquePaths.length} unique path(s): ${uniquePaths.join(', ')}`, dryRun);
674
+ (0, constants_1.logInfo)(`Would update ${gitignoreTarget} with ${uniquePaths.length} unique path(s): ${uniquePaths.join(', ')}`, dryRun);
667
675
  }
668
676
  else {
669
- await (0, GitignoreUtils_1.updateGitignore)(projectRoot, uniquePaths);
670
- (0, constants_1.logInfo)(`Updated .gitignore with ${uniquePaths.length} unique path(s) in the Ruler block.`, dryRun);
677
+ await (0, GitignoreUtils_1.updateGitignore)(projectRoot, uniquePaths, gitignoreTarget);
678
+ (0, constants_1.logInfo)(`Updated ${gitignoreTarget} with ${uniquePaths.length} unique path(s) in the Ruler block.`, dryRun);
671
679
  }
672
680
  }
673
681
  }
package/dist/lib.js CHANGED
@@ -62,7 +62,7 @@ function resolveSkillsEnabled(cliFlag, configSetting) {
62
62
  * @param projectRoot Root directory of the project
63
63
  * @param includedAgents Optional list of agent name filters (case-insensitive substrings)
64
64
  */
65
- async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cliMcpEnabled = true, cliMcpStrategy, cliGitignoreEnabled, verbose = false, dryRun = false, localOnly = false, nested = false, backup = true, skillsEnabled) {
65
+ async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cliMcpEnabled = true, cliMcpStrategy, cliGitignoreEnabled, verbose = false, dryRun = false, localOnly = false, nested = false, backup = true, skillsEnabled, cliGitignoreLocal) {
66
66
  // Load configuration and rules
67
67
  (0, constants_1.logVerbose)(`Loading configuration from project root: ${projectRoot}`, verbose);
68
68
  if (configPath) {
@@ -128,7 +128,7 @@ async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cli
128
128
  const skillsPaths = await getSkillsGitignorePaths(projectRoot, selectedAgents);
129
129
  allGeneratedPaths = [...generatedPaths, ...skillsPaths];
130
130
  }
131
- await (0, apply_engine_1.updateGitignore)(projectRoot, allGeneratedPaths, loadedConfig, cliGitignoreEnabled, dryRun);
131
+ await (0, apply_engine_1.updateGitignore)(projectRoot, allGeneratedPaths, loadedConfig, cliGitignoreEnabled, dryRun, cliGitignoreLocal);
132
132
  }
133
133
  /**
134
134
  * Normalizes per-agent config keys to agent identifiers for consistent lookup.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intellectronica/ruler",
3
- "version": "0.3.34",
3
+ "version": "0.3.35",
4
4
  "description": "Ruler — apply the same rules to all coding agents",
5
5
  "main": "dist/lib.js",
6
6
  "scripts": {