@intellectronica/ruler 0.3.30 → 0.3.32

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
@@ -54,40 +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) | 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` | - | - |
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` | - | - |
91
91
 
92
92
  ## Getting Started
93
93
 
@@ -139,8 +139,8 @@ This is your central hub for all AI agent instructions:
139
139
  4. Remaining discovered `.md` files under `.ruler/` (and subdirectories) in sorted order
140
140
  - **Rule Files (`*.md`)**: Discovered recursively from `.ruler/` or `$XDG_CONFIG_HOME/ruler` and concatenated in the order above
141
141
  - **Concatenation Marker**: Each file's content is prepended with `<!-- Source: <relative_path_to_md_file> -->` for traceability
142
- - **`ruler.toml`**: Master configuration for Ruler's behavior, agent selection, and output paths
143
- - **`mcp.json`**: Shared MCP server settings
142
+ - **`ruler.toml`**: Master configuration for Ruler's behavior, agent selection, output paths, and MCP server settings
143
+ - **`mcp.json`**: (Legacy, deprecated) Shared MCP server settings - no longer scaffolded but still supported for backward compatibility
144
144
 
145
145
  This ordering lets you keep a short, high-impact root `AGENTS.md` (e.g. executive project summary) while housing detailed guidance inside `.ruler/`.
146
146
 
@@ -241,6 +241,8 @@ The `apply` command looks for `.ruler/` in the current directory tree, reading t
241
241
  | `--nested` | Enable nested rule loading (default: inherit from config or disabled). |
242
242
  | `--no-nested` | Disable nested rule loading even if `nested = true` in config. |
243
243
  | `--backup` | Toggle creation of `.bak` backup files (default: enabled). |
244
+ | `--skills` | Enable skills support (experimental, default: enabled). |
245
+ | `--no-skills` | Disable skills support. |
244
246
  | `--dry-run` | Preview changes without writing files. |
245
247
  | `--local-only` | Skip `$XDG_CONFIG_HOME` when looking for configuration. |
246
248
  | `--verbose` / `-v` | Display detailed output during execution. |
@@ -101,7 +101,20 @@ async function readMarkdownFiles(rulerDir) {
101
101
  const entries = await fs_1.promises.readdir(dir, { withFileTypes: true });
102
102
  for (const entry of entries) {
103
103
  const fullPath = path.join(dir, entry.name);
104
- if (entry.isDirectory()) {
104
+ // Resolve symlinks to determine actual type
105
+ let isDir = entry.isDirectory();
106
+ let isFile = entry.isFile();
107
+ if (entry.isSymbolicLink()) {
108
+ try {
109
+ const stat = await fs_1.promises.stat(fullPath);
110
+ isDir = stat.isDirectory();
111
+ isFile = stat.isFile();
112
+ }
113
+ catch {
114
+ continue; // skip broken symlinks
115
+ }
116
+ }
117
+ if (isDir) {
105
118
  // Skip .ruler/skills; skills are propagated separately and should not be concatenated
106
119
  const relativeFromRoot = path.relative(rulerDir, fullPath);
107
120
  const isSkillsDir = relativeFromRoot === constants_1.SKILLS_DIR ||
@@ -111,7 +124,7 @@ async function readMarkdownFiles(rulerDir) {
111
124
  }
112
125
  await walk(fullPath);
113
126
  }
114
- else if (entry.isFile() && entry.name.endsWith('.md')) {
127
+ else if (isFile && entry.name.endsWith('.md')) {
115
128
  const content = await fs_1.promises.readFile(fullPath, 'utf8');
116
129
  mdFiles.push({ path: fullPath, content });
117
130
  }
@@ -226,6 +239,7 @@ async function findGlobalRulerDir() {
226
239
  */
227
240
  async function findAllRulerDirs(startPath) {
228
241
  const rulerDirs = [];
242
+ const rootPath = path.resolve(startPath);
229
243
  // Search the entire directory tree downwards from startPath
230
244
  async function findRulerDirs(dir) {
231
245
  try {
@@ -239,6 +253,18 @@ async function findAllRulerDirs(startPath) {
239
253
  else {
240
254
  // Recursively search subdirectories (but skip hidden directories like .git)
241
255
  if (!entry.name.startsWith('.')) {
256
+ // Do not cross git repository boundaries (except the starting root)
257
+ const gitDir = path.join(fullPath, '.git');
258
+ try {
259
+ const gitStat = await fs_1.promises.stat(gitDir);
260
+ if (gitStat.isDirectory() &&
261
+ path.resolve(fullPath) !== rootPath) {
262
+ continue;
263
+ }
264
+ }
265
+ catch {
266
+ // no .git boundary, continue traversal
267
+ }
242
268
  await findRulerDirs(fullPath);
243
269
  }
244
270
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intellectronica/ruler",
3
- "version": "0.3.30",
3
+ "version": "0.3.32",
4
4
  "description": "Ruler — apply the same rules to all coding agents",
5
5
  "main": "dist/lib.js",
6
6
  "scripts": {