Skiller — apply the same rules to all coding agents
npm install skillerskillerA Claude-centric fork of ruler with native skills support:
- .claude/skills/ is the committed source of truth for skills
- Bidirectional sync between .mdc and SKILL.md (sibling pattern):
- Create .claude/skills/foo/foo.mdc → auto-generates .claude/skills/foo/SKILL.md
- Create .claude/skills/foo/SKILL.md → auto-generates .claude/skills/foo/foo.mdc
- Sync direction detected via @reference body pattern (SKILL.md with @path = .mdc is source)
- Edit either file, the other stays in sync on next skiller apply
- .claude/rules/ contents are migrated to .claude/skills/ and rules directory is deleted
- Uses @filename syntax instead of merging content
- Claude Code auto-includes referenced files
- Reduces CLAUDE.md size and keeps sources separate
- Other agents still get merged content
- Supports both .md and .mdc files (Nuxt Content, Vue)
- All patterns auto-expand: "components" → "components/*/.{md,mdc}"
- include/exclude glob patterns in [rules]
- Directory names auto-expand to directory/*/.{md,mdc}
- Organize by team/feature, exclude drafts/internal docs
- Default directory is .claude/ (no extra flags needed)
- Skills already in .claude/skills (no copying)
- Single directory for all Claude Code config
- merge_strategy = "cursor" parses .mdc frontmatter
- Only includes rules with alwaysApply: true
- Strips frontmatter, keeps body only
- [backup].enabled = false disables .bak files
---
> Beta Research Preview
>
> - Please test this version carefully in your environment
> - Report issues at https://github.com/udecode/skiller/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:
- Inconsistent guidance across AI tools
- Duplicated effort maintaining multiple config files
- Context drift as project requirements evolve
- Onboarding friction for new AI tools
- Complex project structures requiring context-specific instructions for different components
Skiller 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, Skiller can handle complex project structures with context-specific instructions for different components.
- Centralised Rule Management: Store all AI instructions in a dedicated .claude/ directory using Markdown files
- Nested Rule Loading: Support complex project structures with multiple .claude/ directories for context-specific instructions
- Automatic Distribution: Skiller applies these rules to configuration files of supported AI agents
- Targeted Agent Configuration: Fine-tune which agents are affected and their specific output paths via skiller.toml
- MCP Server Propagation: Manage and distribute Model Context Protocol (MCP) server settings
- .gitignore Automation: Keeps generated agent config files out of version control automatically
- Simple CLI: Easy-to-use commands for initialising and applying configurations
| Agent | Rules File(s) | MCP Configuration / Notes |
| ---------------- | -------------------------------------------------- | ------------------------------------------------ |
| AGENTS.md | AGENTS.md | (pseudo-agent ensuring root AGENTS.md exists) |
| GitHub Copilot | AGENTS.md | .vscode/mcp.json |
| Claude Code | CLAUDE.md (@filename references) | .mcp.json |
| OpenAI Codex CLI | AGENTS.md | .codex/config.toml |
| Jules | AGENTS.md | - |
| Cursor | AGENTS.md | .cursor/mcp.json |
| Windsurf | AGENTS.md | .windsurf/mcp_config.json |
| Cline | .clinerules | - |
| Crush | CRUSH.md | .crush.json |
| Amp | AGENTS.md | - |
| Amazon Q CLI | .amazonq/rules/skiller_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 |
| Junie | .junie/guidelines.md | - |
| AugmentCode | .augment/rules/skiller_augment_instructions.md | - |
| Kilo Code | .kilocode/rules/skiller_kilocode_instructions.md | .kilocode/mcp.json |
| OpenCode | AGENTS.md | opencode.json |
| Goose | .goosehints | - |
| Qwen Code | AGENTS.md | .qwen/settings.json |
| RooCode | AGENTS.md | .roo/mcp.json |
| Zed | AGENTS.md | .zed/settings.json (project root, never $HOME) |
| Trae AI | .trae/rules/project_rules.md | - |
| Warp | WARP.md | - |
| Kiro | .kiro/steering/skiller_kiro_instructions.md | - |
| Firebender | firebender.json | firebender.json (rules and MCP in same file) |
Using npx (for one-off commands):
``bash`
npx skiller@latest apply
1. Navigate to your project's root directory
2. Run skiller init
3. This creates:
- .claude/ directory.claude/AGENTS.md
- : The primary starter Markdown file for your rules.claude/skiller.toml
- : The main configuration file for Skiller
Additionally, you can create a global configuration to use when no local .claude/ directory is found:
`bash`
skiller init --global
The global configuration will be created to $XDG_CONFIG_HOME/skiller (default: ~/.config/skiller).
This is your central hub for all AI agent instructions:
- Primary File Order & Precedence:
1. A repository root AGENTS.md (outside .claude/) if present (highest precedence, prepended).claude/AGENTS.md
2. (new default starter file).md
3. Remaining discovered files under .claude/ (and subdirectories) in sorted order*.md
- Rule Files (): Discovered recursively from .claude/ or $XDG_CONFIG_HOME/skiller and concatenated in the order above--- Source:
- Concatenation Marker: Each file's content is prepended with for traceabilityskiller.toml
- : Master configuration for Skiller's behavior, agent selection, and output pathsmcp.json
- : Shared MCP server settings
This ordering lets you keep a short, high-impact root AGENTS.md (e.g. executive project summary) while housing detailed guidance inside .claude/.
Skiller now supports nested rule loading with the --nested flag, enabling context-specific instructions for different parts of your project:
``
project/
├── .claude/ # Global project rules
│ ├── AGENTS.md
│ └── coding_style.md
├── src/
│ └── .claude/ # Component-specific rules
│ └── api_guidelines.md
├── tests/
│ └── .claude/ # Test-specific rules
│ └── testing_conventions.md
└── docs/
└── .claude/ # Documentation rules
└── writing_style.md
How it works:
- Discover all .claude/ directories in the project hierarchyskiller apply --nested
- Load and concatenate rules from each directory in order
- Decide whether nested mode is enabled using the following precedence:
1. (or --no-nested) takes top prioritynested = true
2. in skiller.tomlnested = true
3. Default to disabled when neither option is provided
- When a run is nested, downstream configs are forced to keep . If a child config attempts to disable it, Skiller keeps nested processing active and emits a warning in the logs.
- Nested processing carries forward each directory's own MCP bundle and configuration settings so that generated files remain scoped to their source directories while being normalized back to the project root.
> [!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:
- Monorepos with multiple services
- Projects with distinct components (frontend/backend)
- Teams needing different instructions for different areas
- Complex codebases with varying standards
Granularity: Break down complex instructions into focused .md files:
- coding_style.mdapi_conventions.md
- project_architecture.md
- security_guidelines.md
-
Example rule file (.claude/python_guidelines.md):
`markdownPython Project Guidelines
- 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
- Use specific exception types rather than generic Exception
- Log errors effectively with context
- Always validate and sanitize user input
- Be mindful of potential injection vulnerabilities
`
Command`bash`
skiller apply [options]
The apply command looks for .claude/ in the current directory tree, reading the first match. If no such directory is found, it will look for a global configuration in $XDG_CONFIG_HOME/skiller.
| Option | Description |
| ------------------------------ | ---------------------------------------------------------------------- |
| --project-root | Project root path (default: current directory). |--agents
| | Comma-separated agent names to target (see supported list below). |--config
| | Custom skiller.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. |--nested
| | Enable nested rule loading (default: inherit from config or disabled). |--no-nested
| | Disable nested rule loading even if nested = true in config. |--backup
| / --no-backup | Enable/disable creation of .bak backup files (default: enabled). |--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:
`bash`
skiller apply
Apply rules only to GitHub Copilot and Claude:
`bash`
skiller apply --agents copilot,claude
Apply rules only to Firebase Studio:
`bash`
skiller apply --agents firebase
Apply rules only to Warp:
`bash`
skiller apply --agents warp
Apply rules only to Trae AI:
`bash`
skiller apply --agents trae
Apply rules only to RooCode:
`bash`
skiller apply --agents roo
Use a specific configuration file:
`bash`
skiller apply --config ./team-configs/skiller.frontend.toml
Apply rules with verbose output:
`bash`
skiller apply --verbose
Apply rules but skip MCP and .gitignore updates:
`bash`
skiller apply --no-mcp --no-gitignore
CommandThe revert command safely undoes all changes made by skiller apply, restoring your project to its pre-skiller 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:
- Clean slate: Remove all skiller-generated files to start fresh
- Restore originals: Revert modified files back to their original state
- Selective cleanup: Remove configurations for specific agents only
- Safe experimentation: Try skiller without fear of permanent changes
`bash`
skiller revert [options]
| Option | Description |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| --project-root | Path to your project's root (default: current directory) |--agents
| | Comma-separated list of agent names to revert (agentsmd, aider, amazonqcli, amp, augmentcode, claude, cline, codex, copilot, crush, cursor, firebase, firebender, gemini-cli, goose, jules, junie, kilocode, kiro, opencode, openhands, qwen, roo, trae, warp, windsurf, zed) |--config
| | Path to a custom skiller.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 .claude directories, ignore global config |
Revert all skiller changes:
`bash`
skiller revert
Preview what would be reverted (dry-run):
`bash`
skiller revert --dry-run
Revert only specific agents:
`bash`
skiller revert --agents claude,copilot
Revert with detailed output:
`bash`
skiller revert --verbose
Keep backup files after reverting:
`bash`
skiller revert --keep-backups
) in DetailDefaults to .claude/skiller.toml in the project root. Override with --config CLI option.
`tomlDefault agents to run when --agents is not specified
Uses case-insensitive substring matching
default_agents = ["copilot", "claude", "aider"]
[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"
[agents.claude]
enabled = true
output_path = "CLAUDE.md"
[agents.aider]
enabled = true
output_path_instructions = "AGENTS.md"
output_path_config = ".aider.conf.yml"
[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.kilocode]
enabled = true
output_path = ".kilocode/rules/skiller_kilocode_instructions.md"
[agents.warp]
enabled = true
output_path = "WARP.md"
`
1. CLI flags (e.g., --agents, --no-mcp, --mcp-overwrite, --no-gitignore)skiller.toml
2. Settings in (default_agents, specific agent settings, global sections)
3. Skiller's built-in defaults (all agents enabled, standard output paths, MCP enabled with 'merge')
MCP provides broader context to AI models through server configurations. Skiller can manage and distribute these settings across compatible agents.
You can now define MCP servers directly in skiller.toml using the [mcp_servers. syntax:
`tomlGlobal MCP behavior
[mcp]
enabled = true
merge_strategy = "merge" # or "overwrite"
[mcp_servers.filesystem.env]
API_KEY = "your-api-key"
[mcp_servers.search.headers]
Authorization = "Bearer your-token"
"X-API-Version" = "v1"
`
When both TOML and JSON configurations are present:
1. TOML servers take precedence over JSON servers with the same name
2. Servers are merged from both sources (unless using overwrite strategy)
3. Deprecation warning is shown encouraging migration to TOML (warning shown once per run)
Local/stdio servers require a command field:
`toml
[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):
`toml
[mcp_servers.remote_server]
url = "https://api.example.com"
[mcp_servers.remote_server.headers]
Authorization = "Bearer token"
`
Skiller uses this configuration with the merge (default) or overwrite strategy, controlled by skiller.toml or CLI flags.
Home Directory Safety: Skiller 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:
`bash`
export CODEX_HOME="$(pwd)/.codex"
Skiller can manage and propagate Claude Code-compatible skills to supported AI agents. Skills are stored in .claude/skills/ as the committed source of truth and are automatically discovered by Claude Code.
Skills are specialized knowledge packages that extend AI agent capabilities with domain-specific expertise, workflows, or tool integrations. Skiller discovers skills in your .claude/skills/ directory and keeps them in sync.
Skills can be organized flat or nested:
``
.claude/skills/
├── my-skill/
│ ├── my-skill.mdc # Skill content (body)
│ └── SKILL.md # @reference to my-skill.mdc (frontmatter here)
├── another-skill/
│ ├── another-skill.mdc # Generated from SKILL.md body
│ ├── SKILL.md # Manually created skill (now @reference)
│ ├── helper.py # Optional: additional resources (scripts)
│ └── reference.md # Optional: additional resources (docs)
Each skill can be defined in two ways:
1. Standalone .mdc file - Simple skills can be a single .mdc file at the skills rootSKILL.md
2. Skill folder with - Complex skills with additional resources
Skiller provides bidirectional sync between .mdc files and SKILL.md folders:
| Scenario | Sync Direction |
|----------|---------------|
| .mdc exists, no SKILL.md | → Generate SKILL.md with @reference to .mdc |SKILL.md
| body is @reference | .mdc is source of truth (frontmatter in SKILL.md) |SKILL.md
| has full content | → Generate .mdc from body, update SKILL.md to @reference |
The @reference body pattern indicates that the .mdc file contains the skill content:
`yaml
---
name: my-skill
description: My custom skill
---
@.claude/skills/my-skill/my-skill.mdc
`
Content from .claude/rules/ is automatically migrated to .claude/skills/ during skiller apply, then the rules directory is deleted:
`
.claude/rules/docx/
├── SKILL.md # Makes this a skill folder
├── script.sh # Helper script
└── templates/ # Subdirectory
└── default.docx # Template file
→ Migrated to:
.claude/skills/docx/
├── docx.mdc # Generated from SKILL.md body
├── SKILL.md # Updated to @reference
├── script.sh # Copied automatically
└── templates/ # Copied automatically
└── default.docx # Copied automatically
.claude/rules/ → Deleted after migration
`
Skills support is enabled by default but can be controlled via:
CLI flags:
`bashEnable skills (default)
skiller apply --skills
Configuration in
skiller.toml:`toml
[skills]
enabled = true # or false to disable
`$3
Skiller validates discovered skills and issues warnings for:
- Missing required file (
SKILL.md)
- Invalid directory structures (directories without SKILL.md and no sub-skills)Warnings don't prevent propagation but help identify potential issues.
$3
Test skills propagation without making changes:
`bash
skiller apply --dry-run
`This shows which skills would be synced and validated.
$3
`bash
Option 1: Create a skill using .mdc file
cat > .claude/skills/my-skill.mdc << 'EOF'
---
description: My custom skill
---My Custom Skill
This skill provides specialized knowledge for...
EOF
Option 2: Create a skill folder directly
mkdir -p .claude/skills/my-skill
cat > .claude/skills/my-skill/SKILL.md << 'EOF'
---
name: my-skill
description: My custom skill
---My Custom Skill
This skill provides specialized knowledge for...
EOF
Apply to sync skills (runs bidirectional sync)
skiller applySkills are now available to Claude Code via .claude/skills/
`.gitignore IntegrationSkiller automatically manages your
.gitignore file to keep generated agent configuration files out of version control.$3
- Creates or updates
.gitignore in your project root
- Adds paths to a managed block marked with # START Skiller Generated Files and # END Skiller Generated Files
- Preserves existing content outside this block
- Sorts paths alphabetically and uses relative POSIX-style paths$3
`gitignore
Your existing rules
node_modules/
*.logSTART Skiller Generated Files
.aider.conf.yml
.clinerules
AGENTS.md
CLAUDE.md
END Skiller Generated Files
dist/
`$3
- CLI flags:
--gitignore or --no-gitignore
- Configuration: [gitignore].enabled in skiller.toml
- Default: enabledPractical Usage Scenarios
$3
`bash
Initialize Skiller in your project
cd your-project
skiller initEdit the generated files
- Add your coding guidelines to .claude/AGENTS.md (or keep adding additional .md files)
- Customize .claude/skiller.toml if needed
Apply rules to all AI agents
skiller apply
`$3
For large projects with multiple components or services, enable nested rule loading so each directory keeps its own rules and MCP bundle:
`bash
Set up nested .claude directories
mkdir -p src/.claude tests/.claude docs/.claudeAdd component-specific instructions
echo "# API Design Guidelines" > src/.claude/api_rules.md
echo "# Testing Best Practices" > tests/.claude/test_rules.md
echo "# Documentation Standards" > docs/.claude/docs_rules.md
``toml
.claude/skiller.toml
nested = true
``bash
The CLI inherits nested mode from skiller.toml
skiller apply --verboseOverride from the CLI at any time
skiller apply --no-nested
`This creates context-specific instructions for different parts of your project while maintaining global rules in the root
.claude/ 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.
$3
1. Create
.claude/coding_standards.md, .claude/api_usage.md
2. Commit the .claude directory to your repository
3. Team members pull changes and run skiller apply to update their local AI agent configurations$3
1. Detail your project's architecture in
.claude/project_overview.md
2. Describe primary data structures in .claude/data_models.md
3. Run skiller apply to help AI tools provide more relevant suggestions$3
`json
{
"scripts": {
"skiller:apply": "skiller apply",
"dev": "npm run skiller:apply && your_dev_command",
"precommit": "npm run skiller:apply"
}
}
`$3
`yaml
.github/workflows/skiller-check.yml
name: Check Skiller Configuration
on:
pull_request:
paths: ['.claude/**']jobs:
check-skiller:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install Skiller
run: npm install -g skiller
- name: Apply Skiller configuration
run: skiller apply --no-gitignore
- name: Check for uncommitted changes
run: |
if [[ -n $(git status --porcelain) ]]; then
echo "::error::Skiller configuration is out of sync!"
echo "Please run 'skiller apply' locally and commit the changes."
exit 1
fi
`Troubleshooting
$3
"Cannot find module" errors:
- Ensure Skiller is installed globally:
npm install -g skiller
- Or use npx skiller@latestPermission denied errors:
- On Unix systems, you may need
sudo for global installationAgent files not updating:
- Check if the agent is enabled in
skiller.toml
- Verify agent isn't excluded by --agents flag
- Use --verbose to see detailed execution logsConfiguration validation errors:
- Skiller now validates
skiller.toml format and will show specific error details
- Check that all configuration values match the expected types and formats$3
Use
--verbose flag to see detailed execution logs:`bash
skiller apply --verbose
`This shows:
- Configuration loading details
- Agent selection logic
- File processing information
- MCP configuration steps
FAQ
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 skiller.toml or by passing skiller 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 .claude/ 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 Skiller for an agent?
A: Set
enabled = false in skiller.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: Skiller creates backups with
.bak extension before overwriting any existing files.Q: Can I run Skiller in CI/CD pipelines?
A: Yes! Use
skiller apply --no-gitignore in CI to avoid modifying .gitignore. See the GitHub Actions example above.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: Skiller writes a
settings.json in 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:
skiller init now only adds example MCP server sections to skiller.toml instead of creating .claude/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/skiller_kiro_instructions.md.Development
$3
`bash
git clone https://github.com/udecode/skiller.git
cd skiller
npm install
npm run build
`$3
`bash
Run all tests
npm testRun tests with coverage
npm run test:coverageRun tests in watch mode
npm run test:watch
`$3
`bash
Run linting
npm run lintRun formatting
npm run format
``