Ruler — apply the same rules to all coding agents
2,910
stars
931
commits
TypeScript
primary language
Sep 2, 2026
updated
Animation by Isaac Flath of Elite AI-Assisted Coding ➡︎ |
|
Beta Research Preview
- Please test this version carefully in your environment
- Report issues at https://github.com/intellectronica/ruler/issues
Managing instructions across multiple AI coding tools becomes complex as your team grows. Different agents (GitHub Copilot, Claude, Cursor, Aider, etc.) require their own configuration files, leading to:
Ruler solves this by providing a single source of truth for all your AI agent instructions, automatically distributing them to the right configuration files. With support for nested rule loading, Ruler can handle complex project structures with context-specific instructions for different components.
.ruler/ directory using Markdown files.ruler/ directories for context-specific instructionsruler.toml.gitignore Automation: Keeps generated agent config files out of version control automatically| Agent | Rules File(s) | MCP Configuration / Notes | Skills Support / Location | Subagents Support / Location |
|---|---|---|---|---|
| AGENTS.md | AGENTS.md | (pseudo-agent ensuring root AGENTS.md exists) | - | - |
| GitHub Copilot | AGENTS.md | .mcp.json | .claude/skills/ | .github/agents/ |
| Claude Code | CLAUDE.md | .mcp.json | .claude/skills/ | .claude/agents/ |
| OpenAI Codex CLI | AGENTS.md | .codex/config.toml | .agents/skills/ | .codex/agents/ (.toml) |
| Pi Coding Agent | AGENTS.md | - | .pi/skills/ | - |
| Jules | AGENTS.md | - | - | - |
| Cursor | AGENTS.md | .cursor/mcp.json | .cursor/skills/ | .cursor/agents/ |
| Windsurf | AGENTS.md | .windsurf/mcp_config.json | .windsurf/skills/ | - |
| Cline | .clinerules | - | - | - |
| Crush | CRUSH.md | .crush.json | - | - |
| Amp | AGENTS.md | - | .agents/skills/ | - |
| Antigravity | .agent/rules/ruler.md | - | .agent/skills/ | - |
| Amazon Q CLI | .amazonq/rules/ruler_q_rules.md | .amazonq/mcp.json | - | - |
| Aider | AGENTS.md, .aider.conf.yml | .mcp.json | - | - |
| Firebase Studio | .idx/airules.md | .idx/mcp.json | - | - |
| Open Hands | .openhands/microagents/repo.md | config.toml | - | - |
| Gemini CLI | AGENTS.md | .gemini/settings.json | .gemini/skills/ | - |
| Junie | .junie/guidelines.md | .junie/mcp/mcp.json | .junie/skills/ | - |
| AugmentCode | .augment/rules/ruler_augment_instructions.md | - | - | - |
| Kilo Code | AGENTS.md | .kilocode/mcp.json | .claude/skills/ | - |
| OpenCode | AGENTS.md | opencode.json | .opencode/skills/ | - |
| Goose | .goosehints | - | .agents/skills/ | - |
| Qwen Code | AGENTS.md | .qwen/settings.json | - | - |
| RooCode | AGENTS.md | .roo/mcp.json | .roo/skills/ | - |
| Zed | AGENTS.md | .zed/settings.json (project root, never $HOME) | .agents/skills/ | - |
| Trae AI | .trae/rules/project_rules.md | - | - | - |
| Warp | WARP.md | - | - | - |
| Kiro | .kiro/steering/ruler_kiro_instructions.md | .kiro/settings/mcp.json | .kiro/skills/ | - |
| Firebender | firebender.json | firebender.json (rules and MCP in same file) | - | - |
| Factory Droid | AGENTS.md | .factory/mcp.json | .factory/skills/ | - |
| Mistral Vibe | AGENTS.md | .vibe/config.toml | .vibe/skills/ | - |
| JetBrains AI Assistant | .aiassistant/rules/AGENTS.md | - | - | - |
Requires Node.js ^20.19.0 || ^22.12.0 || >=23.
Global Installation (Recommended for CLI use):
npm install -g @intellectronica/ruler
Using npx (for one-off commands):
npx @intellectronica/ruler apply
ruler init.ruler/ directory.ruler/AGENTS.md: The primary starter Markdown file for your rules.ruler/ruler.toml: The main configuration file for Ruler (now contains sample MCP server sections; legacy .ruler/mcp.json no longer scaffolded).ruler/instructions.md, it is still respected when AGENTS.md is absent. (The prior runtime warning was removed.)Additionally, you can create a global configuration to use when no local .ruler/ directory is found:
ruler init --global
The global configuration will be created to $XDG_CONFIG_HOME/ruler (default: ~/.config/ruler).
.ruler/ DirectoryThis is your central hub for all AI agent instructions:
AGENTS.md (outside .ruler/) if present (highest precedence, prepended).ruler/AGENTS.md (new default starter file).ruler/instructions.md (used as the primary file only if .ruler/AGENTS.md is absent; no longer emits a deprecation warning).md files under .ruler/ (and subdirectories) in sorted order, including instructions.md when both top-level files exist*.md): Discovered recursively from .ruler/ or $XDG_CONFIG_HOME/ruler and concatenated in the order above<!-- Source: <relative_path_to_md_file> --> for traceabilityruler.toml: Master configuration for Ruler's behavior, agent selection, output paths, and MCP server settingsmcp.json: (Legacy, deprecated) Shared MCP server settings - no longer scaffolded but still supported for backward compatibilityThis ordering lets you keep a short, high-impact root AGENTS.md (e.g. executive project summary) while housing detailed guidance inside .ruler/.
Ruler now supports nested rule loading with the --nested flag, enabling context-specific instructions for different parts of your project:
project/
├── .ruler/ # Global project rules
│ ├── AGENTS.md
│ └── coding_style.md
├── src/
│ └── .ruler/ # Component-specific rules
│ └── api_guidelines.md
├── tests/
│ └── .ruler/ # Test-specific rules
│ └── testing_conventions.md
└── docs/
└── .ruler/ # Documentation rules
└── writing_style.md
How it works:
.ruler/ directories in the project hierarchyruler apply --nested (or --no-nested) takes top prioritynested = true in ruler.tomlnested = true. If a child config attempts to disable it, Ruler keeps nested processing active and emits a warning in the logs.[!CAUTION] Nested mode is experimental and may change in future releases. The CLI logs this warning the first time a nested run is detected so you know the behavior may evolve.
Perfect for:
Granularity: Break down complex instructions into focused .md files:
coding_style.mdapi_conventions.mdproject_architecture.mdsecurity_guidelines.mdExample rule file (.ruler/python_guidelines.md):
# Python Project Guidelines
## General Style
- Follow PEP 8 for all Python code
- Use type hints for all function signatures and complex variables
- Keep functions short and focused on a single task
## Error Handling
- Use specific exception types rather than generic `Exception`
- Log errors effectively with context
## Security
- Always validate and sanitize user input
- Be mindful of potential injection vulnerabilities
apply Commandruler apply [options]
The apply command searches upward from --project-root (default: current directory) for the nearest .ruler/ directory. If no local .ruler/ directory is found, it falls back to $XDG_CONFIG_HOME/ruler.
| Option | Description |
|---|---|
--project-root <path> | Project root path (default: current directory). |
--agents <agent1,agent2,...> | Comma-separated agent names to target (see supported list below). |
--config <path> | Custom ruler.toml path. |
--mcp / --with-mcp | Enable applying MCP server configurations (default: true). |
--no-mcp | Disable applying MCP server configurations. |
--mcp-overwrite | Overwrite native MCP config instead of merging. |
--gitignore | Enable automatic .gitignore updates (default: true). |
--no-gitignore | Disable automatic .gitignore updates. |
--gitignore-local | Write managed ignore entries to .git/info/exclude instead. |
--nested | Enable nested rule loading (default: inherit from config or disabled). |
--no-nested | Disable nested rule loading even if nested = true in config. |
--backup | Enable creation of .bak backup files (default: from config or enabled). |
--no-backup | Disable creation of .bak backup files. |
--skills | Enable skills support (experimental, default: enabled). |
--no-skills | Disable skills support. |
--subagents | Enable subagents support (experimental, default: disabled). |
--no-subagents | Disable subagents support. |
--dry-run | Preview changes without writing files. |
--local-only | Skip $XDG_CONFIG_HOME when looking for configuration. |
--verbose / -v | Display detailed output during execution. |
Apply rules to all configured agents:
ruler apply
Apply rules only to GitHub Copilot and Claude:
ruler apply --agents copilot,claude
Apply rules only to Firebase Studio:
ruler apply --agents firebase
Apply rules only to Warp:
ruler apply --agents warp
Apply rules only to Trae AI:
ruler apply --agents trae
Apply rules only to RooCode:
ruler apply --agents roo
Use a specific configuration file:
ruler apply --config ./team-configs/ruler.frontend.toml
Apply rules with verbose output:
ruler apply --verbose
Apply rules but skip MCP and .gitignore updates:
ruler apply --no-mcp --no-gitignore
revert CommandThe revert command safely undoes all changes made by ruler apply, restoring your project to its pre-ruler state. It intelligently restores files from backups (.bak files) when available, or removes generated files that didn't exist before.
When experimenting with different rule configurations or switching between projects, you may want to:
ruler revert [options]
| Option | Description |
|---|---|
--project-root <path> | Path to your project's root (default: current directory) |
--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, jetbrains-ai, jules, junie, kilocode, kiro, mistral, opencode, openhands, pi, qwen, roo, trae, warp, windsurf, zed) |
--config <path> | Path to a custom ruler.toml configuration file |
--keep-backups | Keep backup files (.bak) after restoration (default: false) |
--dry-run | Preview changes without actually reverting files |
--verbose / -v | Display detailed output during execution |
--local-only | Only search for local .ruler directories, ignore global config |
--nested | Enable nested revert processing (default: inherit from config or disabled) |
--no-nested | Disable nested revert processing even if nested = true in config |
Revert all ruler changes:
ruler revert
Preview what would be reverted (dry-run):
ruler revert --dry-run
Revert only specific agents:
ruler revert --agents claude,copilot
Revert with detailed output:
ruler revert --verbose
Keep backup files after reverting:
ruler revert --keep-backups
ruler.toml) in DetailDefaults to .ruler/ruler.toml in the project root. Override with --config CLI option.
# Default agents to run when --agents is not specified
# Uses case-insensitive substring matching
default_agents = ["copilot", "claude", "aider"]
# --- Global MCP Server Configuration ---
[mcp]
# Enable/disable MCP propagation globally (default: true)
enabled = true
# Global merge strategy: 'merge' or 'overwrite' (default: 'merge')
merge_strategy = "merge"
# --- MCP Server Definitions ---
[mcp_servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/project"]
[mcp_servers.git]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-git", "--repository", "."]
[mcp_servers.remote_api]
url = "https://api.example.com"
[mcp_servers.remote_api.headers]
Authorization = "Bearer your-token"
# --- Global .gitignore Configuration ---
[gitignore]
# Enable/disable automatic .gitignore updates (default: true)
enabled = true
# Write managed entries to .git/info/exclude instead of .gitignore (default: false)
local = false
# --- Backup Configuration ---
[backup]
# Enable/disable creation of .bak backup files (default: true)
enabled = true
# --- Agent-Specific Configurations ---
[agents.copilot]
enabled = true
[agents.claude]
enabled = true
output_path = "CLAUDE.md"
[agents.aider]
enabled = true
output_path_instructions = "AGENTS.md"
output_path_config = ".aider.conf.yml"
# OpenAI Codex CLI agent and MCP config
[agents.codex]
enabled = true
output_path = "AGENTS.md"
output_path_config = ".codex/config.toml"
# Agent-specific MCP configuration for Codex CLI
[agents.codex.mcp]
enabled = true
merge_strategy = "merge"
[agents.firebase]
enabled = true
output_path = ".idx/airules.md"
[agents.gemini-cli]
enabled = true
[agents.jules]
enabled = true
[agents.junie]
enabled = true
output_path = ".junie/guidelines.md"
[agents.junie.mcp]
enabled = true
merge_strategy = "merge"
# Agent-specific MCP configuration
[agents.cursor.mcp]
enabled = true
merge_strategy = "merge"
# Disable specific agents
[agents.windsurf]
enabled = false
[agents.kilocode]
enabled = true
output_path = "AGENTS.md"
[agents.warp]
enabled = true
output_path = "WARP.md"
--agents, --no-mcp, --mcp-overwrite, --no-gitignore)ruler.toml (default_agents, specific agent settings, global sections)MCP provides broader context to AI models through server configurations. Ruler can manage and distribute these settings across compatible agents.
You can now define MCP servers directly in ruler.toml using the [mcp_servers.<name>] syntax:
# Global MCP behavior
[mcp]
enabled = true
merge_strategy = "merge" # or "overwrite"
# Local (stdio) server
[mcp_servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/project"]
[mcp_servers.filesystem.env]
API_KEY = "your-api-key"
# Remote server
[mcp_servers.search]
url = "https://mcp.example.com"
[mcp_servers.search.headers]
Authorization = "Bearer your-token"
"X-API-Version" = "v1"
Agent-specific MCP servers can be defined under [agents.<agent>.mcp_servers.<name>].
They are applied only to that agent and override global servers with the same name:
[agents.cursor.mcp_servers.slack]
url = "https://mcp.slack.com/mcp"
auth = { CLIENT_ID = "CURSOR_ID" }
[agents.claude.mcp_servers.slack]
type = "http"
url = "https://mcp.slack.com/mcp"
oauth = { clientId = "CLAUDE_ID", callbackPort = 3118 }
.ruler/mcp.json (Deprecated)For backward compatibility, you can still use the JSON format; a warning is issued encouraging migration to TOML. The file is no longer created during ruler init.
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/path/to/project"
]
},
"git": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-git", "--repository", "."]
}
}
}
When both TOML and JSON configurations are present:
Local/stdio servers require a command field:
[mcp_servers.local_server]
command = "node"
args = ["server.js"]
[mcp_servers.local_server.env]
DEBUG = "1"
Remote servers require a url field (headers optional; bearer Authorization token auto-extracted for OpenHands when possible):
[mcp_servers.remote_server]
url = "https://api.example.com"
[mcp_servers.remote_server.headers]
Authorization = "Bearer token"
Ruler uses this configuration with the merge (default) or overwrite strategy, controlled by ruler.toml or CLI flags.
Home Directory Safety: Ruler never writes MCP configuration files outside your project root. Any historical references to user home directories (e.g. ~/.codeium/windsurf/mcp_config.json or ~/.zed/settings.json) have been removed; only project-local paths are targeted.
Note for OpenAI Codex CLI: To apply the local Codex CLI MCP configuration, set the CODEX_HOME environment variable to your project’s .codex directory:
export CODEX_HOME="$(pwd)/.codex"
⚠️ Experimental Feature: Skills support is currently experimental. Skills are only propagated to agents with native skills support; other agents are skipped with a warning.
Ruler can manage and propagate skills to supported AI agents. Skills are stored in .ruler/skills/ and are automatically distributed to compatible agents when you run ruler apply.
Skills are specialized knowledge packages that extend AI agent capabilities with domain-specific expertise, workflows, or tool integrations. Ruler discovers skills in your .ruler/skills/ directory and propagates them to compatible agents:
.claude/skills/.claude/skills/ (shared with Claude Code).claude/skills/ (shared with Claude Code).agents/skills/ (shared with Goose, Amp, and Zed).opencode/skills/.pi/skills/.agents/skills/.agents/skills/ (shared with Goose).agents/skills/ (shared with Goose).agent/skills/.factory/skills/.vibe/skills/.roo/skills/.gemini/skills/.junie/skills/.cursor/skills/.windsurf/skills/.kiro/skills/Skills can be organized flat or nested:
.ruler/skills/
├── my-skill/
│ ├── SKILL.md # Required: skill instructions/knowledge
│ ├── helper.py # Optional: additional resources (scripts)
│ └── reference.md # Optional: additional resources (docs)
└── another-skill/
└── SKILL.md
Each skill must contain:
SKILL.md - Primary skill file with instructions or knowledge baseSkills can optionally include additional resources like:
Skills support is enabled by default but can be controlled via:
CLI flags:
# Enable skills (default)
ruler apply --skills
# Disable skills
ruler apply --no-skills
Configuration in ruler.toml:
[skills]
enabled = true # or false to disable
If you run Ruler for agents that do not support native skills, Ruler logs a warning and skips skills propagation for those agents.
.gitignore IntegrationWhen skills support is enabled and gitignore integration is active, Ruler automatically adds:
.claude/skills/ (for Claude Code, GitHub Copilot, and Kilo Code).agents/skills/ (for OpenAI Codex CLI, Goose, Amp, and Zed).opencode/skills/ (for OpenCode).pi/skills/ (for Pi Coding Agent).agent/skills/ (for Antigravity).factory/skills/ (for Factory Droid).vibe/skills/ (for Mistral Vibe).roo/skills/ (for Roo Code).gemini/skills/ (for Gemini CLI).junie/skills/ (for Junie).cursor/skills/ (for Cursor).windsurf/skills/ (for Windsurf).kiro/skills/ (for Kiro)to your .gitignore file within the managed Ruler block.
Ruler validates discovered skills and issues warnings for:
SKILL.md)SKILL.md and no sub-skills)Warnings don't prevent propagation but help identify potential issues.
Test skills propagation without making changes:
ruler apply --dry-run
This shows which skills would be copied.
# 1. Add a skill to your project
mkdir -p .ruler/skills/my-skill
cat > .ruler/skills/my-skill/SKILL.md << 'EOF'
# My Custom Skill
This skill provides specialized knowledge for...
## Usage
When working on this project, always follow these guidelines:
- Use TypeScript for all new code
- Write tests for all features
- Follow the existing code style
EOF
# 2. Apply to all agents (skills enabled by default)
ruler apply
# 3. Skills are now available to compatible agents:
# - Claude Code, GitHub Copilot & Kilo Code: .claude/skills/my-skill/
# - OpenAI Codex CLI, Goose, Amp & Zed: .agents/skills/my-skill/
# - OpenCode: .opencode/skills/my-skill/
# - Pi Coding Agent: .pi/skills/my-skill/
# - Antigravity: .agent/skills/my-skill/
# - Factory Droid: .factory/skills/my-skill/
# - Mistral Vibe: .vibe/skills/my-skill/
# - Roo Code: .roo/skills/my-skill/
# - Gemini CLI: .gemini/skills/my-skill/
# - Junie: .junie/skills/my-skill/
# - Cursor: .cursor/skills/my-skill/
# - Windsurf: .windsurf/skills/my-skill/
# - Kiro: .kiro/skills/my-skill/
⚠️ Experimental: Subagents support is experimental and behavior may change in future releases.
Ruler can distribute named, delegatable subagents from a single source of truth (.ruler/agents/) to each agent's native subagent location. Each source file is one Markdown file with YAML frontmatter; Ruler transforms it into the format the target agent expects.
For agents with a native subagent primitive, Ruler writes one file per subagent into the target directory:
| Agent | Target location | Format |
|---|---|---|
| Claude Code | .claude/agents/<relative-path>.md | Markdown + YAML frontmatter |
| Cursor | .cursor/agents/<relative-path>.md | Markdown + YAML frontmatter |
| OpenAI Codex CLI | .codex/agents/<relative-path>.toml | TOML (one self-contained file per agent) |
| GitHub Copilot | .github/agents/<relative-path>.md | Markdown + YAML frontmatter |
Other agents (Windsurf, RooCode, Aider, Gemini CLI, …) do not yet have a comparable native subagent primitive and are skipped with a warning. Subagent propagation will be added when those agents ship a comparable file format.
Author each subagent as .ruler/agents/<name>.md (nested folders are supported and preserved in outputs):
---
name: code-reviewer
description: Use PROACTIVELY after a feature/fix is implemented. Reviews against SOLID/DRY/KISS. Read-only.
tools: [Read, Grep, Glob, Bash]
model: inherit
readonly: true
is_background: false
---
# Code Reviewer
You operate in a fresh context window with read-only access. Your job is to
review the diff and surrounding code against the design principles and return
a structured verdict.
Required frontmatter fields:
| Field | Type | Notes |
|---|---|---|
name | string | Must match the filename stem (code-reviewer.md → name: code-reviewer). |
description | string | When the parent agent should delegate to this subagent. |
Optional frontmatter fields:
| Field | Type | Used by | Default behavior |
|---|---|---|---|
tools | string[] | Claude (verbatim), Copilot (mapped to aliases) | Cursor / Codex ignore; omitted if absent. |
model | string | All four targets | Cursor defaults to inherit; others omit. |
readonly | boolean | Cursor (verbatim), Codex (sandbox_mode), Copilot (disable-model-invocation) | Defaults to false for Cursor; omitted otherwise. |
is_background | boolean | Cursor only | Defaults to false for Cursor. |
For GitHub Copilot, source tools (Claude vocabulary: Read, Grep, Bash, …) are translated to Copilot's aliases (read, search, execute, …). Tools that do not have a Copilot equivalent are dropped silently on a normal apply; pass --verbose (or use --dry-run to preview) to see which tools were dropped.
Subagent propagation is disabled by default. Opt in via CLI flag or ruler.toml:
ruler apply --subagents # enable subagent propagation for one run
# .ruler/ruler.toml
[agents]
enabled = true
# include_in_rules = true # also append .ruler/agents/*.md into top-level CLAUDE.md / AGENTS.md (default: false)
# cleanup_orphaned = true # allow ruler to delete stale native subagent dirs (default: false)
Note: the previous release used
[subagents]for these keys.[subagents]is still honored as a fallback with a deprecation warning, and will be removed in a future release. Please migrate to[agents].
[agents] enabled controls only native subagent propagation from .ruler/agents/. It is independent from [agents.<name>] enabled (which toggles per-coding-agent output like CLAUDE.md / AGENTS.md).
CLI flags take precedence over ruler.toml, which takes precedence over the default (disabled).
Source files are validated at discovery time:
name or description are skipped with a warning.name does not match the filename stem are skipped with a warning.Use --dry-run to preview which files would be written without touching disk.
.gitignore IntegrationWhen subagents are enabled, the four target directories are added to the Ruler-managed block of .gitignore:
.claude/agents/
.cursor/agents/
.codex/agents/
.github/agents/
Use --no-gitignore to opt out.
Subagent propagation does not currently have explicit ruler revert support. By default, ruler apply is non-destructive and leaves existing native subagent directories untouched when subagents are disabled or missing. To allow automatic cleanup of stale generated directories, set [agents] cleanup_orphaned = true, then disable subagents ([agents] enabled = false or --no-subagents) and run ruler apply.
# 1. Author a subagent in your project
mkdir -p .ruler/agents
cat > .ruler/agents/code-reviewer.md << 'EOF'
---
name: code-reviewer
description: Reviews changes against SOLID/DRY/KISS
tools: [Read, Grep, Glob]
readonly: true
---
You review code changes for quality.
EOF
# 2. Opt subagents in (default is disabled — see [agents] section above)
echo -e "\n[agents]\nenabled = true" >> .ruler/ruler.toml
# 3. Apply
ruler apply
# 4. The subagent is now available in each agent's native location:
# - Claude Code: .claude/agents/code-reviewer.md
# - Cursor: .cursor/agents/code-reviewer.md
# - Codex CLI: .codex/agents/code-reviewer.toml
# - GitHub Copilot: .github/agents/code-reviewer.md
[agents] cleanup_orphaned = true and a subsequent apply..gitignore IntegrationRuler automatically manages your .gitignore file to keep generated agent configuration files out of version control.
.gitignore in your project root# START Ruler Generated Files and # END Ruler Generated Files.gitignore Section (sample - actual list depends on enabled agents)# Your existing rules
node_modules/
*.log
# START Ruler Generated Files
.aider.conf.yml
.clinerules
AGENTS.md
CLAUDE.md
# END Ruler Generated Files
dist/
--gitignore, --no-gitignore, --gitignore-local, --no-gitignore-local[gitignore].enabled and [gitignore].local in ruler.toml--backup, --no-backup[backup].enabled in ruler.toml# Initialize Ruler in your project
cd your-project
ruler init
# Edit the generated files
# - Add your coding guidelines to .ruler/AGENTS.md (or keep adding additional .md files)
# - Customize .ruler/ruler.toml if needed
# Apply rules to all AI agents
ruler apply
When using the default git worktree add command (which is also run by agent apps such as Claude Code or Codex through the interface), the gitignored files are not copied over. You will need to ask your agent to run ruler apply at the start of every session.
As an alternative you can commit your default agents files to source control.
# .ruler/ruler.toml
default_agents = ["claude", "codex"]
[gitignore]
enabled = false
# Do not ignore AGENTS.md and CLAUDE.md
/.claude/*
!/.claude/skills/
/.codex/*
!/.codex/skills/
/.cursor
/AGENTS.md.bak
/CLAUDE.md.bak
To avoid having other contributors commit instructions outside of .ruler you can setup a github action to check there is no diff when running ruler apply in CI.
# .github/workflows/ruler-check.yml
# Verifies the committed agent files (AGENTS.md, CLAUDE.md, skills) match the .ruler/ source.
# They are committed so a fresh clone/worktree has guidance immediately; this guards against drift.
name: Ruler guidance in sync
on:
pull_request:
push:
branches:
- main
- 'build/**'
permissions:
contents: read
env:
CI_NODE_VERSION: 24.15.0
jobs:
ruler-check:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- uses: pnpm/action-setup@v5
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: ${{ env.CI_NODE_VERSION }}
cache: 'pnpm'
- name: Verify committed agent files match .ruler/
run: |
pnpm dlx @intellectronica/ruler apply --no-gitignore --no-mcp
DRIFT="$(git status --porcelain -- AGENTS.md CLAUDE.md .claude/skills .codex/skills)"
if [ -n "$DRIFT" ]; then
echo "::error::Committed agent files are out of sync with .ruler/. Run 'pnpm dlx @intellectronica/ruler apply --no-gitignore --no-mcp' and commit the result."
echo "$DRIFT"
git --no-pager diff -- AGENTS.md CLAUDE.md .claude/skills .codex/skills
exit 1
fi
echo "Agent files are in sync with .ruler/."
For large projects with multiple components or services, enable nested rule loading so each directory keeps its own rules and MCP bundle:
# Set up nested .ruler directories
mkdir -p src/.ruler tests/.ruler docs/.ruler
# Add component-specific instructions
echo "# API Design Guidelines" > src/.ruler/api_rules.md
echo "# Testing Best Practices" > tests/.ruler/test_rules.md
echo "# Documentation Standards" > docs/.ruler/docs_rules.md
# .ruler/ruler.toml
nested = true
# The CLI inherits nested mode from ruler.toml
ruler apply --verbose
# Override from the CLI at any time
ruler apply --no-nested
This creates context-specific instructions for different parts of your project while maintaining global rules in the root .ruler/ directory. Nested runs automatically keep every nested config enabled even if a child tries to disable it.
[!NOTE] The CLI prints "Nested mode is experimental and may change in future releases." the first time nested processing runs. Expect refinements in future versions.
.ruler/coding_standards.md, .ruler/api_usage.md.ruler directory to your repositoryruler apply to update their local AI agent configurations.ruler/project_overview.md.ruler/data_models.mdruler apply to help AI tools provide more relevant suggestions{
"scripts": {
"ruler:apply": "ruler apply",
"dev": "npm run ruler:apply && your_dev_command",
"precommit": "npm run ruler:apply"
}
}
# .github/workflows/ruler-check.yml
name: Check Ruler Configuration
on:
pull_request:
paths: ['.ruler/**']
jobs:
check-ruler:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install Ruler
run: npm install -g @intellectronica/ruler
- name: Apply Ruler configuration
run: ruler apply --no-gitignore
- name: Check for uncommitted changes
run: |
if [[ -n $(git status --porcelain) ]]; then
echo "::error::Ruler configuration is out of sync!"
echo "Please run 'ruler apply' locally and commit the changes."
exit 1
fi
"Cannot find module" errors:
npm install -g @intellectronica/rulernpx @intellectronica/rulerPermission denied errors:
sudo for global installationAgent files not updating:
ruler.toml--agents flag--verbose to see detailed execution logsConfiguration validation errors:
ruler.toml format and will show specific error detailsUse --verbose flag to see detailed execution logs:
ruler apply --verbose
This shows:
Q: Can I use different rules for different agents? A: Currently, all agents receive the same concatenated rules. For agent-specific instructions, include sections in your rule files like "## GitHub Copilot Specific" or "## Aider Configuration".
Q: How do I set up different instructions for different parts of my project?
A: Enable nested mode either by setting nested = true in ruler.toml or by passing ruler apply --nested. The CLI inherits the config setting by default, but --no-nested always wins if you need to opt out for a run. Nested mode keeps loading rules (and MCP settings) from every .ruler/ directory in the hierarchy, forces child configs to remain nested, and logs "Nested mode is experimental and may change in future releases." if any nested processing occurs.
Q: How do I temporarily disable Ruler for an agent?
A: Set enabled = false in ruler.toml under [agents.agentname], or use --agents flag to specify only the agents you want.
Q: What happens to my existing agent configuration files?
A: Ruler creates backups with .bak extension before overwriting any existing files.
Q: Can I run Ruler in CI/CD pipelines?
A: Yes! Use ruler apply --no-gitignore in CI to avoid modifying .gitignore. See the GitHub Actions example above.
Q: How do I migrate from older versions using instructions.md?
A: Simply rename .ruler/instructions.md to .ruler/AGENTS.md (recommended). If you keep the legacy file and omit AGENTS.md, Ruler will still use it (without emitting the old deprecation warning). Having both causes AGENTS.md to take precedence; the legacy file is still concatenated afterward.
Q: How does OpenHands MCP propagation classify servers?
A: Local stdio servers become stdio_servers. Remote URLs containing /sse are classified as sse_servers; others become shttp_servers. Bearer tokens in an Authorization header are extracted into api_key where possible.
Q: Where is Zed configuration written now?
A: Ruler writes .zed/settings.json inside the project root (not the user home dir) and transforms MCP server definitions to Zed's context_servers format including source: "custom".
Q: What changed about MCP initialization?
A: ruler init now only adds example MCP server sections to ruler.toml instead of creating .ruler/mcp.json. The JSON file is still consumed if present, but TOML servers win on name conflicts.
Q: Is Kiro supported?
A: Yes. Kiro receives concatenated rules at .kiro/steering/ruler_kiro_instructions.md, MCP servers at .kiro/settings/mcp.json, and skills at .kiro/skills/.
git clone https://github.com/intellectronica/ruler.git
cd ruler
npm install
npm run build
# Run all tests
npm test
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watch
# Run linting
npm run lint
# Run formatting
npm run format
Contributions are welcome! Please:
For bugs and feature requests, please open an issue.
MIT
© Eleanor Berger
ai.intellectronica.net
TypeScript
99.8%
Ruler — apply the same rules to all coding agents
2,910
stars
931
commits
TypeScript
primary language
Sep 2, 2026
updated
Animation by Isaac Flath of Elite AI-Assisted Coding ➡︎ |
|
Beta Research Preview
- Please test this version carefully in your environment
- Report issues at https://github.com/intellectronica/ruler/issues
Managing instructions across multiple AI coding tools becomes complex as your team grows. Different agents (GitHub Copilot, Claude, Cursor, Aider, etc.) require their own configuration files, leading to:
Ruler solves this by providing a single source of truth for all your AI agent instructions, automatically distributing them to the right configuration files. With support for nested rule loading, Ruler can handle complex project structures with context-specific instructions for different components.
.ruler/ directory using Markdown files.ruler/ directories for context-specific instructionsruler.toml.gitignore Automation: Keeps generated agent config files out of version control automatically| Agent | Rules File(s) | MCP Configuration / Notes | Skills Support / Location | Subagents Support / Location |
|---|---|---|---|---|
| AGENTS.md | AGENTS.md | (pseudo-agent ensuring root AGENTS.md exists) | - | - |
| GitHub Copilot | AGENTS.md | .mcp.json | .claude/skills/ | .github/agents/ |
| Claude Code | CLAUDE.md | .mcp.json | .claude/skills/ | .claude/agents/ |
| OpenAI Codex CLI | AGENTS.md | .codex/config.toml | .agents/skills/ | .codex/agents/ (.toml) |
| Pi Coding Agent | AGENTS.md | - | .pi/skills/ | - |
| Jules | AGENTS.md | - | - | - |
| Cursor | AGENTS.md | .cursor/mcp.json | .cursor/skills/ | .cursor/agents/ |
| Windsurf | AGENTS.md | .windsurf/mcp_config.json | .windsurf/skills/ | - |
| Cline | .clinerules | - | - | - |
| Crush | CRUSH.md | .crush.json | - | - |
| Amp | AGENTS.md | - | .agents/skills/ | - |
| Antigravity | .agent/rules/ruler.md | - | .agent/skills/ | - |
| Amazon Q CLI | .amazonq/rules/ruler_q_rules.md | .amazonq/mcp.json | - | - |
| Aider | AGENTS.md, .aider.conf.yml | .mcp.json | - | - |
| Firebase Studio | .idx/airules.md | .idx/mcp.json | - | - |
| Open Hands | .openhands/microagents/repo.md | config.toml | - | - |
| Gemini CLI | AGENTS.md | .gemini/settings.json | .gemini/skills/ | - |
| Junie | .junie/guidelines.md | .junie/mcp/mcp.json | .junie/skills/ | - |
| AugmentCode | .augment/rules/ruler_augment_instructions.md | - | - | - |
| Kilo Code | AGENTS.md | .kilocode/mcp.json | .claude/skills/ | - |
| OpenCode | AGENTS.md | opencode.json | .opencode/skills/ | - |
| Goose | .goosehints | - | .agents/skills/ | - |
| Qwen Code | AGENTS.md | .qwen/settings.json | - | - |
| RooCode | AGENTS.md | .roo/mcp.json | .roo/skills/ | - |
| Zed | AGENTS.md | .zed/settings.json (project root, never $HOME) | .agents/skills/ | - |
| Trae AI | .trae/rules/project_rules.md | - | - | - |
| Warp | WARP.md | - | - | - |
| Kiro | .kiro/steering/ruler_kiro_instructions.md | .kiro/settings/mcp.json | .kiro/skills/ | - |
| Firebender | firebender.json | firebender.json (rules and MCP in same file) | - | - |
| Factory Droid | AGENTS.md | .factory/mcp.json | .factory/skills/ | - |
| Mistral Vibe | AGENTS.md | .vibe/config.toml | .vibe/skills/ | - |
| JetBrains AI Assistant | .aiassistant/rules/AGENTS.md | - | - | - |
Requires Node.js ^20.19.0 || ^22.12.0 || >=23.
Global Installation (Recommended for CLI use):
npm install -g @intellectronica/ruler
Using npx (for one-off commands):
npx @intellectronica/ruler apply
ruler init.ruler/ directory.ruler/AGENTS.md: The primary starter Markdown file for your rules.ruler/ruler.toml: The main configuration file for Ruler (now contains sample MCP server sections; legacy .ruler/mcp.json no longer scaffolded).ruler/instructions.md, it is still respected when AGENTS.md is absent. (The prior runtime warning was removed.)Additionally, you can create a global configuration to use when no local .ruler/ directory is found:
ruler init --global
The global configuration will be created to $XDG_CONFIG_HOME/ruler (default: ~/.config/ruler).
.ruler/ DirectoryThis is your central hub for all AI agent instructions:
AGENTS.md (outside .ruler/) if present (highest precedence, prepended).ruler/AGENTS.md (new default starter file).ruler/instructions.md (used as the primary file only if .ruler/AGENTS.md is absent; no longer emits a deprecation warning).md files under .ruler/ (and subdirectories) in sorted order, including instructions.md when both top-level files exist*.md): Discovered recursively from .ruler/ or $XDG_CONFIG_HOME/ruler and concatenated in the order above<!-- Source: <relative_path_to_md_file> --> for traceabilityruler.toml: Master configuration for Ruler's behavior, agent selection, output paths, and MCP server settingsmcp.json: (Legacy, deprecated) Shared MCP server settings - no longer scaffolded but still supported for backward compatibilityThis ordering lets you keep a short, high-impact root AGENTS.md (e.g. executive project summary) while housing detailed guidance inside .ruler/.
Ruler now supports nested rule loading with the --nested flag, enabling context-specific instructions for different parts of your project:
project/
├── .ruler/ # Global project rules
│ ├── AGENTS.md
│ └── coding_style.md
├── src/
│ └── .ruler/ # Component-specific rules
│ └── api_guidelines.md
├── tests/
│ └── .ruler/ # Test-specific rules
│ └── testing_conventions.md
└── docs/
└── .ruler/ # Documentation rules
└── writing_style.md
How it works:
.ruler/ directories in the project hierarchyruler apply --nested (or --no-nested) takes top prioritynested = true in ruler.tomlnested = true. If a child config attempts to disable it, Ruler keeps nested processing active and emits a warning in the logs.[!CAUTION] Nested mode is experimental and may change in future releases. The CLI logs this warning the first time a nested run is detected so you know the behavior may evolve.
Perfect for:
Granularity: Break down complex instructions into focused .md files:
coding_style.mdapi_conventions.mdproject_architecture.mdsecurity_guidelines.mdExample rule file (.ruler/python_guidelines.md):
# Python Project Guidelines
## General Style
- Follow PEP 8 for all Python code
- Use type hints for all function signatures and complex variables
- Keep functions short and focused on a single task
## Error Handling
- Use specific exception types rather than generic `Exception`
- Log errors effectively with context
## Security
- Always validate and sanitize user input
- Be mindful of potential injection vulnerabilities
apply Commandruler apply [options]
The apply command searches upward from --project-root (default: current directory) for the nearest .ruler/ directory. If no local .ruler/ directory is found, it falls back to $XDG_CONFIG_HOME/ruler.
| Option | Description |
|---|---|
--project-root <path> | Project root path (default: current directory). |
--agents <agent1,agent2,...> | Comma-separated agent names to target (see supported list below). |
--config <path> | Custom ruler.toml path. |
--mcp / --with-mcp | Enable applying MCP server configurations (default: true). |
--no-mcp | Disable applying MCP server configurations. |
--mcp-overwrite | Overwrite native MCP config instead of merging. |
--gitignore | Enable automatic .gitignore updates (default: true). |
--no-gitignore | Disable automatic .gitignore updates. |
--gitignore-local | Write managed ignore entries to .git/info/exclude instead. |
--nested | Enable nested rule loading (default: inherit from config or disabled). |
--no-nested | Disable nested rule loading even if nested = true in config. |
--backup | Enable creation of .bak backup files (default: from config or enabled). |
--no-backup | Disable creation of .bak backup files. |
--skills | Enable skills support (experimental, default: enabled). |
--no-skills | Disable skills support. |
--subagents | Enable subagents support (experimental, default: disabled). |
--no-subagents | Disable subagents support. |
--dry-run | Preview changes without writing files. |
--local-only | Skip $XDG_CONFIG_HOME when looking for configuration. |
--verbose / -v | Display detailed output during execution. |
Apply rules to all configured agents:
ruler apply
Apply rules only to GitHub Copilot and Claude:
ruler apply --agents copilot,claude
Apply rules only to Firebase Studio:
ruler apply --agents firebase
Apply rules only to Warp:
ruler apply --agents warp
Apply rules only to Trae AI:
ruler apply --agents trae
Apply rules only to RooCode:
ruler apply --agents roo
Use a specific configuration file:
ruler apply --config ./team-configs/ruler.frontend.toml
Apply rules with verbose output:
ruler apply --verbose
Apply rules but skip MCP and .gitignore updates:
ruler apply --no-mcp --no-gitignore
revert CommandThe revert command safely undoes all changes made by ruler apply, restoring your project to its pre-ruler state. It intelligently restores files from backups (.bak files) when available, or removes generated files that didn't exist before.
When experimenting with different rule configurations or switching between projects, you may want to:
ruler revert [options]
| Option | Description |
|---|---|
--project-root <path> | Path to your project's root (default: current directory) |
--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, jetbrains-ai, jules, junie, kilocode, kiro, mistral, opencode, openhands, pi, qwen, roo, trae, warp, windsurf, zed) |
--config <path> | Path to a custom ruler.toml configuration file |
--keep-backups | Keep backup files (.bak) after restoration (default: false) |
--dry-run | Preview changes without actually reverting files |
--verbose / -v | Display detailed output during execution |
--local-only | Only search for local .ruler directories, ignore global config |
--nested | Enable nested revert processing (default: inherit from config or disabled) |
--no-nested | Disable nested revert processing even if nested = true in config |
Revert all ruler changes:
ruler revert
Preview what would be reverted (dry-run):
ruler revert --dry-run
Revert only specific agents:
ruler revert --agents claude,copilot
Revert with detailed output:
ruler revert --verbose
Keep backup files after reverting:
ruler revert --keep-backups
ruler.toml) in DetailDefaults to .ruler/ruler.toml in the project root. Override with --config CLI option.
# Default agents to run when --agents is not specified
# Uses case-insensitive substring matching
default_agents = ["copilot", "claude", "aider"]
# --- Global MCP Server Configuration ---
[mcp]
# Enable/disable MCP propagation globally (default: true)
enabled = true
# Global merge strategy: 'merge' or 'overwrite' (default: 'merge')
merge_strategy = "merge"
# --- MCP Server Definitions ---
[mcp_servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/project"]
[mcp_servers.git]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-git", "--repository", "."]
[mcp_servers.remote_api]
url = "https://api.example.com"
[mcp_servers.remote_api.headers]
Authorization = "Bearer your-token"
# --- Global .gitignore Configuration ---
[gitignore]
# Enable/disable automatic .gitignore updates (default: true)
enabled = true
# Write managed entries to .git/info/exclude instead of .gitignore (default: false)
local = false
# --- Backup Configuration ---
[backup]
# Enable/disable creation of .bak backup files (default: true)
enabled = true
# --- Agent-Specific Configurations ---
[agents.copilot]
enabled = true
[agents.claude]
enabled = true
output_path = "CLAUDE.md"
[agents.aider]
enabled = true
output_path_instructions = "AGENTS.md"
output_path_config = ".aider.conf.yml"
# OpenAI Codex CLI agent and MCP config
[agents.codex]
enabled = true
output_path = "AGENTS.md"
output_path_config = ".codex/config.toml"
# Agent-specific MCP configuration for Codex CLI
[agents.codex.mcp]
enabled = true
merge_strategy = "merge"
[agents.firebase]
enabled = true
output_path = ".idx/airules.md"
[agents.gemini-cli]
enabled = true
[agents.jules]
enabled = true
[agents.junie]
enabled = true
output_path = ".junie/guidelines.md"
[agents.junie.mcp]
enabled = true
merge_strategy = "merge"
# Agent-specific MCP configuration
[agents.cursor.mcp]
enabled = true
merge_strategy = "merge"
# Disable specific agents
[agents.windsurf]
enabled = false
[agents.kilocode]
enabled = true
output_path = "AGENTS.md"
[agents.warp]
enabled = true
output_path = "WARP.md"
--agents, --no-mcp, --mcp-overwrite, --no-gitignore)ruler.toml (default_agents, specific agent settings, global sections)MCP provides broader context to AI models through server configurations. Ruler can manage and distribute these settings across compatible agents.
You can now define MCP servers directly in ruler.toml using the [mcp_servers.<name>] syntax:
# Global MCP behavior
[mcp]
enabled = true
merge_strategy = "merge" # or "overwrite"
# Local (stdio) server
[mcp_servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/project"]
[mcp_servers.filesystem.env]
API_KEY = "your-api-key"
# Remote server
[mcp_servers.search]
url = "https://mcp.example.com"
[mcp_servers.search.headers]
Authorization = "Bearer your-token"
"X-API-Version" = "v1"
Agent-specific MCP servers can be defined under [agents.<agent>.mcp_servers.<name>].
They are applied only to that agent and override global servers with the same name:
[agents.cursor.mcp_servers.slack]
url = "https://mcp.slack.com/mcp"
auth = { CLIENT_ID = "CURSOR_ID" }
[agents.claude.mcp_servers.slack]
type = "http"
url = "https://mcp.slack.com/mcp"
oauth = { clientId = "CLAUDE_ID", callbackPort = 3118 }
.ruler/mcp.json (Deprecated)For backward compatibility, you can still use the JSON format; a warning is issued encouraging migration to TOML. The file is no longer created during ruler init.
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/path/to/project"
]
},
"git": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-git", "--repository", "."]
}
}
}
When both TOML and JSON configurations are present:
Local/stdio servers require a command field:
[mcp_servers.local_server]
command = "node"
args = ["server.js"]
[mcp_servers.local_server.env]
DEBUG = "1"
Remote servers require a url field (headers optional; bearer Authorization token auto-extracted for OpenHands when possible):
[mcp_servers.remote_server]
url = "https://api.example.com"
[mcp_servers.remote_server.headers]
Authorization = "Bearer token"
Ruler uses this configuration with the merge (default) or overwrite strategy, controlled by ruler.toml or CLI flags.
Home Directory Safety: Ruler never writes MCP configuration files outside your project root. Any historical references to user home directories (e.g. ~/.codeium/windsurf/mcp_config.json or ~/.zed/settings.json) have been removed; only project-local paths are targeted.
Note for OpenAI Codex CLI: To apply the local Codex CLI MCP configuration, set the CODEX_HOME environment variable to your project’s .codex directory:
export CODEX_HOME="$(pwd)/.codex"
⚠️ Experimental Feature: Skills support is currently experimental. Skills are only propagated to agents with native skills support; other agents are skipped with a warning.
Ruler can manage and propagate skills to supported AI agents. Skills are stored in .ruler/skills/ and are automatically distributed to compatible agents when you run ruler apply.
Skills are specialized knowledge packages that extend AI agent capabilities with domain-specific expertise, workflows, or tool integrations. Ruler discovers skills in your .ruler/skills/ directory and propagates them to compatible agents:
.claude/skills/.claude/skills/ (shared with Claude Code).claude/skills/ (shared with Claude Code).agents/skills/ (shared with Goose, Amp, and Zed).opencode/skills/.pi/skills/.agents/skills/.agents/skills/ (shared with Goose).agents/skills/ (shared with Goose).agent/skills/.factory/skills/.vibe/skills/.roo/skills/.gemini/skills/.junie/skills/.cursor/skills/.windsurf/skills/.kiro/skills/Skills can be organized flat or nested:
.ruler/skills/
├── my-skill/
│ ├── SKILL.md # Required: skill instructions/knowledge
│ ├── helper.py # Optional: additional resources (scripts)
│ └── reference.md # Optional: additional resources (docs)
└── another-skill/
└── SKILL.md
Each skill must contain:
SKILL.md - Primary skill file with instructions or knowledge baseSkills can optionally include additional resources like:
Skills support is enabled by default but can be controlled via:
CLI flags:
# Enable skills (default)
ruler apply --skills
# Disable skills
ruler apply --no-skills
Configuration in ruler.toml:
[skills]
enabled = true # or false to disable
If you run Ruler for agents that do not support native skills, Ruler logs a warning and skips skills propagation for those agents.
.gitignore IntegrationWhen skills support is enabled and gitignore integration is active, Ruler automatically adds:
.claude/skills/ (for Claude Code, GitHub Copilot, and Kilo Code).agents/skills/ (for OpenAI Codex CLI, Goose, Amp, and Zed).opencode/skills/ (for OpenCode).pi/skills/ (for Pi Coding Agent).agent/skills/ (for Antigravity).factory/skills/ (for Factory Droid).vibe/skills/ (for Mistral Vibe).roo/skills/ (for Roo Code).gemini/skills/ (for Gemini CLI).junie/skills/ (for Junie).cursor/skills/ (for Cursor).windsurf/skills/ (for Windsurf).kiro/skills/ (for Kiro)to your .gitignore file within the managed Ruler block.
Ruler validates discovered skills and issues warnings for:
SKILL.md)SKILL.md and no sub-skills)Warnings don't prevent propagation but help identify potential issues.
Test skills propagation without making changes:
ruler apply --dry-run
This shows which skills would be copied.
# 1. Add a skill to your project
mkdir -p .ruler/skills/my-skill
cat > .ruler/skills/my-skill/SKILL.md << 'EOF'
# My Custom Skill
This skill provides specialized knowledge for...
## Usage
When working on this project, always follow these guidelines:
- Use TypeScript for all new code
- Write tests for all features
- Follow the existing code style
EOF
# 2. Apply to all agents (skills enabled by default)
ruler apply
# 3. Skills are now available to compatible agents:
# - Claude Code, GitHub Copilot & Kilo Code: .claude/skills/my-skill/
# - OpenAI Codex CLI, Goose, Amp & Zed: .agents/skills/my-skill/
# - OpenCode: .opencode/skills/my-skill/
# - Pi Coding Agent: .pi/skills/my-skill/
# - Antigravity: .agent/skills/my-skill/
# - Factory Droid: .factory/skills/my-skill/
# - Mistral Vibe: .vibe/skills/my-skill/
# - Roo Code: .roo/skills/my-skill/
# - Gemini CLI: .gemini/skills/my-skill/
# - Junie: .junie/skills/my-skill/
# - Cursor: .cursor/skills/my-skill/
# - Windsurf: .windsurf/skills/my-skill/
# - Kiro: .kiro/skills/my-skill/
⚠️ Experimental: Subagents support is experimental and behavior may change in future releases.
Ruler can distribute named, delegatable subagents from a single source of truth (.ruler/agents/) to each agent's native subagent location. Each source file is one Markdown file with YAML frontmatter; Ruler transforms it into the format the target agent expects.
For agents with a native subagent primitive, Ruler writes one file per subagent into the target directory:
| Agent | Target location | Format |
|---|---|---|
| Claude Code | .claude/agents/<relative-path>.md | Markdown + YAML frontmatter |
| Cursor | .cursor/agents/<relative-path>.md | Markdown + YAML frontmatter |
| OpenAI Codex CLI | .codex/agents/<relative-path>.toml | TOML (one self-contained file per agent) |
| GitHub Copilot | .github/agents/<relative-path>.md | Markdown + YAML frontmatter |
Other agents (Windsurf, RooCode, Aider, Gemini CLI, …) do not yet have a comparable native subagent primitive and are skipped with a warning. Subagent propagation will be added when those agents ship a comparable file format.
Author each subagent as .ruler/agents/<name>.md (nested folders are supported and preserved in outputs):
---
name: code-reviewer
description: Use PROACTIVELY after a feature/fix is implemented. Reviews against SOLID/DRY/KISS. Read-only.
tools: [Read, Grep, Glob, Bash]
model: inherit
readonly: true
is_background: false
---
# Code Reviewer
You operate in a fresh context window with read-only access. Your job is to
review the diff and surrounding code against the design principles and return
a structured verdict.
Required frontmatter fields:
| Field | Type | Notes |
|---|---|---|
name | string | Must match the filename stem (code-reviewer.md → name: code-reviewer). |
description | string | When the parent agent should delegate to this subagent. |
Optional frontmatter fields:
| Field | Type | Used by | Default behavior |
|---|---|---|---|
tools | string[] | Claude (verbatim), Copilot (mapped to aliases) | Cursor / Codex ignore; omitted if absent. |
model | string | All four targets | Cursor defaults to inherit; others omit. |
readonly | boolean | Cursor (verbatim), Codex (sandbox_mode), Copilot (disable-model-invocation) | Defaults to false for Cursor; omitted otherwise. |
is_background | boolean | Cursor only | Defaults to false for Cursor. |
For GitHub Copilot, source tools (Claude vocabulary: Read, Grep, Bash, …) are translated to Copilot's aliases (read, search, execute, …). Tools that do not have a Copilot equivalent are dropped silently on a normal apply; pass --verbose (or use --dry-run to preview) to see which tools were dropped.
Subagent propagation is disabled by default. Opt in via CLI flag or ruler.toml:
ruler apply --subagents # enable subagent propagation for one run
# .ruler/ruler.toml
[agents]
enabled = true
# include_in_rules = true # also append .ruler/agents/*.md into top-level CLAUDE.md / AGENTS.md (default: false)
# cleanup_orphaned = true # allow ruler to delete stale native subagent dirs (default: false)
Note: the previous release used
[subagents]for these keys.[subagents]is still honored as a fallback with a deprecation warning, and will be removed in a future release. Please migrate to[agents].
[agents] enabled controls only native subagent propagation from .ruler/agents/. It is independent from [agents.<name>] enabled (which toggles per-coding-agent output like CLAUDE.md / AGENTS.md).
CLI flags take precedence over ruler.toml, which takes precedence over the default (disabled).
Source files are validated at discovery time:
name or description are skipped with a warning.name does not match the filename stem are skipped with a warning.Use --dry-run to preview which files would be written without touching disk.
.gitignore IntegrationWhen subagents are enabled, the four target directories are added to the Ruler-managed block of .gitignore:
.claude/agents/
.cursor/agents/
.codex/agents/
.github/agents/
Use --no-gitignore to opt out.
Subagent propagation does not currently have explicit ruler revert support. By default, ruler apply is non-destructive and leaves existing native subagent directories untouched when subagents are disabled or missing. To allow automatic cleanup of stale generated directories, set [agents] cleanup_orphaned = true, then disable subagents ([agents] enabled = false or --no-subagents) and run ruler apply.
# 1. Author a subagent in your project
mkdir -p .ruler/agents
cat > .ruler/agents/code-reviewer.md << 'EOF'
---
name: code-reviewer
description: Reviews changes against SOLID/DRY/KISS
tools: [Read, Grep, Glob]
readonly: true
---
You review code changes for quality.
EOF
# 2. Opt subagents in (default is disabled — see [agents] section above)
echo -e "\n[agents]\nenabled = true" >> .ruler/ruler.toml
# 3. Apply
ruler apply
# 4. The subagent is now available in each agent's native location:
# - Claude Code: .claude/agents/code-reviewer.md
# - Cursor: .cursor/agents/code-reviewer.md
# - Codex CLI: .codex/agents/code-reviewer.toml
# - GitHub Copilot: .github/agents/code-reviewer.md
[agents] cleanup_orphaned = true and a subsequent apply..gitignore IntegrationRuler automatically manages your .gitignore file to keep generated agent configuration files out of version control.
.gitignore in your project root# START Ruler Generated Files and # END Ruler Generated Files.gitignore Section (sample - actual list depends on enabled agents)# Your existing rules
node_modules/
*.log
# START Ruler Generated Files
.aider.conf.yml
.clinerules
AGENTS.md
CLAUDE.md
# END Ruler Generated Files
dist/
--gitignore, --no-gitignore, --gitignore-local, --no-gitignore-local[gitignore].enabled and [gitignore].local in ruler.toml--backup, --no-backup[backup].enabled in ruler.toml# Initialize Ruler in your project
cd your-project
ruler init
# Edit the generated files
# - Add your coding guidelines to .ruler/AGENTS.md (or keep adding additional .md files)
# - Customize .ruler/ruler.toml if needed
# Apply rules to all AI agents
ruler apply
When using the default git worktree add command (which is also run by agent apps such as Claude Code or Codex through the interface), the gitignored files are not copied over. You will need to ask your agent to run ruler apply at the start of every session.
As an alternative you can commit your default agents files to source control.
# .ruler/ruler.toml
default_agents = ["claude", "codex"]
[gitignore]
enabled = false
# Do not ignore AGENTS.md and CLAUDE.md
/.claude/*
!/.claude/skills/
/.codex/*
!/.codex/skills/
/.cursor
/AGENTS.md.bak
/CLAUDE.md.bak
To avoid having other contributors commit instructions outside of .ruler you can setup a github action to check there is no diff when running ruler apply in CI.
# .github/workflows/ruler-check.yml
# Verifies the committed agent files (AGENTS.md, CLAUDE.md, skills) match the .ruler/ source.
# They are committed so a fresh clone/worktree has guidance immediately; this guards against drift.
name: Ruler guidance in sync
on:
pull_request:
push:
branches:
- main
- 'build/**'
permissions:
contents: read
env:
CI_NODE_VERSION: 24.15.0
jobs:
ruler-check:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- uses: pnpm/action-setup@v5
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: ${{ env.CI_NODE_VERSION }}
cache: 'pnpm'
- name: Verify committed agent files match .ruler/
run: |
pnpm dlx @intellectronica/ruler apply --no-gitignore --no-mcp
DRIFT="$(git status --porcelain -- AGENTS.md CLAUDE.md .claude/skills .codex/skills)"
if [ -n "$DRIFT" ]; then
echo "::error::Committed agent files are out of sync with .ruler/. Run 'pnpm dlx @intellectronica/ruler apply --no-gitignore --no-mcp' and commit the result."
echo "$DRIFT"
git --no-pager diff -- AGENTS.md CLAUDE.md .claude/skills .codex/skills
exit 1
fi
echo "Agent files are in sync with .ruler/."
For large projects with multiple components or services, enable nested rule loading so each directory keeps its own rules and MCP bundle:
# Set up nested .ruler directories
mkdir -p src/.ruler tests/.ruler docs/.ruler
# Add component-specific instructions
echo "# API Design Guidelines" > src/.ruler/api_rules.md
echo "# Testing Best Practices" > tests/.ruler/test_rules.md
echo "# Documentation Standards" > docs/.ruler/docs_rules.md
# .ruler/ruler.toml
nested = true
# The CLI inherits nested mode from ruler.toml
ruler apply --verbose
# Override from the CLI at any time
ruler apply --no-nested
This creates context-specific instructions for different parts of your project while maintaining global rules in the root .ruler/ directory. Nested runs automatically keep every nested config enabled even if a child tries to disable it.
[!NOTE] The CLI prints "Nested mode is experimental and may change in future releases." the first time nested processing runs. Expect refinements in future versions.
.ruler/coding_standards.md, .ruler/api_usage.md.ruler directory to your repositoryruler apply to update their local AI agent configurations.ruler/project_overview.md.ruler/data_models.mdruler apply to help AI tools provide more relevant suggestions{
"scripts": {
"ruler:apply": "ruler apply",
"dev": "npm run ruler:apply && your_dev_command",
"precommit": "npm run ruler:apply"
}
}
# .github/workflows/ruler-check.yml
name: Check Ruler Configuration
on:
pull_request:
paths: ['.ruler/**']
jobs:
check-ruler:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install Ruler
run: npm install -g @intellectronica/ruler
- name: Apply Ruler configuration
run: ruler apply --no-gitignore
- name: Check for uncommitted changes
run: |
if [[ -n $(git status --porcelain) ]]; then
echo "::error::Ruler configuration is out of sync!"
echo "Please run 'ruler apply' locally and commit the changes."
exit 1
fi
"Cannot find module" errors:
npm install -g @intellectronica/rulernpx @intellectronica/rulerPermission denied errors:
sudo for global installationAgent files not updating:
ruler.toml--agents flag--verbose to see detailed execution logsConfiguration validation errors:
ruler.toml format and will show specific error detailsUse --verbose flag to see detailed execution logs:
ruler apply --verbose
This shows:
Q: Can I use different rules for different agents? A: Currently, all agents receive the same concatenated rules. For agent-specific instructions, include sections in your rule files like "## GitHub Copilot Specific" or "## Aider Configuration".
Q: How do I set up different instructions for different parts of my project?
A: Enable nested mode either by setting nested = true in ruler.toml or by passing ruler apply --nested. The CLI inherits the config setting by default, but --no-nested always wins if you need to opt out for a run. Nested mode keeps loading rules (and MCP settings) from every .ruler/ directory in the hierarchy, forces child configs to remain nested, and logs "Nested mode is experimental and may change in future releases." if any nested processing occurs.
Q: How do I temporarily disable Ruler for an agent?
A: Set enabled = false in ruler.toml under [agents.agentname], or use --agents flag to specify only the agents you want.
Q: What happens to my existing agent configuration files?
A: Ruler creates backups with .bak extension before overwriting any existing files.
Q: Can I run Ruler in CI/CD pipelines?
A: Yes! Use ruler apply --no-gitignore in CI to avoid modifying .gitignore. See the GitHub Actions example above.
Q: How do I migrate from older versions using instructions.md?
A: Simply rename .ruler/instructions.md to .ruler/AGENTS.md (recommended). If you keep the legacy file and omit AGENTS.md, Ruler will still use it (without emitting the old deprecation warning). Having both causes AGENTS.md to take precedence; the legacy file is still concatenated afterward.
Q: How does OpenHands MCP propagation classify servers?
A: Local stdio servers become stdio_servers. Remote URLs containing /sse are classified as sse_servers; others become shttp_servers. Bearer tokens in an Authorization header are extracted into api_key where possible.
Q: Where is Zed configuration written now?
A: Ruler writes .zed/settings.json inside the project root (not the user home dir) and transforms MCP server definitions to Zed's context_servers format including source: "custom".
Q: What changed about MCP initialization?
A: ruler init now only adds example MCP server sections to ruler.toml instead of creating .ruler/mcp.json. The JSON file is still consumed if present, but TOML servers win on name conflicts.
Q: Is Kiro supported?
A: Yes. Kiro receives concatenated rules at .kiro/steering/ruler_kiro_instructions.md, MCP servers at .kiro/settings/mcp.json, and skills at .kiro/skills/.
git clone https://github.com/intellectronica/ruler.git
cd ruler
npm install
npm run build
# Run all tests
npm test
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watch
# Run linting
npm run lint
# Run formatting
npm run format
Contributions are welcome! Please:
For bugs and feature requests, please open an issue.
MIT
© Eleanor Berger
ai.intellectronica.net
TypeScript
99.8%