https://github.com/patrickclery/ruly
CLI tool for managing AI assistant rules and configurations
https://github.com/patrickclery/ruly
Last synced: 4 months ago
JSON representation
CLI tool for managing AI assistant rules and configurations
- Host: GitHub
- URL: https://github.com/patrickclery/ruly
- Owner: patrickclery
- License: mit
- Created: 2025-09-08T19:24:58.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2026-03-03T21:19:09.000Z (4 months ago)
- Last Synced: 2026-03-04T00:49:44.399Z (4 months ago)
- Language: Ruby
- Size: 940 KB
- Stars: 5
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
```
██████╗░██╗░░░██╗██╗░░░░░██╗░░░██╗
██╔══██╗██║░░░██║██║░░░░░╚██╗░██╔╝
██████╔╝██║░░░██║██║░░░░░░╚████╔╝░
██╔══██╗██║░░░██║██║░░░░░░░╚██╔╝░░
██║░░██║╚██████╔╝███████╗░░░██║░░░
╚═╝░░╚═╝░╚═════╝░╚══════╝░░░╚═╝░░░
```
## 🚀 Quick Install
### One-Line Installation
```bash
curl -fsSL https://raw.githubusercontent.com/patrickclery/ruly/main/setup.rb -o /tmp/ruly_setup.rb && ruby /tmp/ruly_setup.rb
```
This will:
- Install Ruly to `~/ruly`
- Add `ruly` command to your PATH
- Set up initial configuration at `~/.config/ruly/profiles.yml`
### Manual Installation
If you prefer to install manually:
```bash
# Clone the repository
git clone https://github.com/patrickclery/ruly.git ~/ruly
cd ~/ruly
# Install dependencies
bundle config set --local path 'vendor/bundle'
bundle install
# Add to PATH (add to your ~/.bashrc or ~/.zshrc)
export PATH="$HOME/ruly/bin:$PATH"
# Initialize configuration
ruly init
```
### Uninstall
To remove Ruly:
```bash
rm -rf ~/ruly
# Remove the PATH export from your shell configuration file
```
### Getting Started
After installation, you can immediately start using Ruly:
```bash
# Initialize configuration (if not done during install)
$ ruly init
# List available commands
$ ruly help
# Combine all rules into one file
$ ruly squash
# Use a specific profile
$ ruly squash starter
# Clean up generated files
$ ruly clean
# List available profiles
$ ruly list-profiles
# Show version
$ ruly version
```
## 🌟 How It Works
### Standalone CLI Tool
Ruly is a standalone command-line tool that manages AI assistant rules:
1. **Simple Installation**: One-line install with curl
2. **Self-Contained**: Everything runs from `~/ruly`
3. **Profile System**: Use pre-configured profiles or create your own
4. **Smart Caching**: Cache compiled profiles for performance
5. **Multiple Formats**: Support for different AI assistants (Claude, Cursor, etc.)
**Benefits:**
- ✅ **Standalone**: No gem installation required
- ✅ **Easy updates**: Just pull the latest changes
- ✅ **No system dependencies**: Self-contained in your home directory
- ✅ **Flexible rules system**: Define your own rules repository or use remote sources
- ✅ **Cross-platform**: Works anywhere Ruby is installed
### What Ruly Does
**The `ruly` command provides:**
- ✅ Combine multiple rule files into one document
- ✅ Use profile collections for different contexts
- ✅ Fetch and include remote GitHub files
- ✅ Cache compiled profiles for performance
- ✅ Support for Claude, Cursor, and other AI assistants
- ✅ Clean up all agent-related files automatically
**Generated Files:**
```
your-project/
├── CLAUDE.local.md # Generated by ruly squash (default)
├── .ruly/
│ └── bin/ # Executable scripts (from scripts: key)
└── .claude/
├── commands/ # Command files for Claude agent
│ ├── bug/ # Bug-related commands
│ ├── pr/ # PR management commands
│ └── workflow/ # Workflow commands
└── skills/ # Skill files for Claude agent
├── debugging/
│ └── SKILL.md
└── pr-review-loop/
└── SKILL.md
```
For other agents:
- **Cursor**: Uses `.cursor/` directory with `.mdc` files
- **Custom**: Specify with `--agent` and `--output-file` options
---
## About Ruly
Ruly is a powerful CLI tool that manages AI assistant rules and configurations for software development projects. It provides a framework for organizing and combining rule files from various sources - your own private repositories, public GitHub repos, or local files - into a single document for AI assistants like Claude or Cursor.
### ⚠️ Important: Rules Not Included
This repository **does not include rule files**. You need to:
1. Create your own rules repository (private or public)
2. Configure profiles to point to your rule sources
3. Use the `ruly init` command to get started with a template
## 🎯 Setting Up Your Rules
### Option 1: Create Your Own Rules Repository
1. **Create a new repository for your rules:**
```bash
# Create a private repository
gh repo create yourusername/rules --private --description "My AI assistant rules"
# Clone it locally
git clone git@github.com:yourusername/rules.git
cd rules
```
2. **Organize your rules:**
```
rules/
├── ruby/
│ ├── common.md
│ ├── rspec.md
│ └── best-practices.md
├── testing/
│ └── patterns.md
├── commands/
│ ├── bug/
│ │ └── diagnose.md
│ └── pr/
│ └── create.md
├── comms/
│ ├── jira/
│ │ ├── common.md # Shared Jira patterns
│ │ └── bin/ # Shell scripts for Jira operations
│ │ └── fetch-jira-details.sh
│ └── ms-teams/
│ ├── common.md # Shared Teams patterns
│ ├── commands/
│ │ └── dm.md # User-facing command
│ └── agents/
│ └── ms-teams-dm.md # Subagent instructions
├── github/
│ ├── pr/
│ │ └── bin/ # Shell scripts for PR operations
│ │ └── fetch-pr-details.sh
│ └── bin/ # General GitHub scripts
│ └── git_prettycommit.rb
└── core/
└── debugging.md
```
**Directory conventions:**
- `commands/` - User-invocable slash commands (e.g., `/ms-teams:dm`). Must be listed under the `commands:` profile key to be output as `.claude/commands/` files.
- `skills/` - Skill files that become `SKILL.md` in `.claude/skills/`. Must be listed under the `skills:` profile key.
- `agents/` - Subagent instruction files (dispatched by orchestrator, not user-invocable)
- `bin/` - Shell scripts and executables. Must be listed under the `scripts:` profile key to be copied to `.claude/scripts/`.
- Root files - Common patterns and shared configuration
### Option 2: Use Multiple Rule Sources
Create `~/.config/ruly/profiles.yml` to combine rules from different repositories:
```yaml
profiles:
my-complete-rules:
description: "Combines personal and company rules"
sources:
# Your personal rules repository
- github: yourusername/rules
branch: main
rules:
- ruby
- testing
- commands
# Company rules (e.g., "FakeCorp")
- github: fakecorp/development-standards
branch: main
rules:
- guidelines/code-review.md
- guidelines/security.md
# Individual files from public repos
- https://github.com/thoughtbot/guides/blob/main/ruby/README.md
```
### Option 3: Quick Start with Init
After installing Ruly, you can quickly get started with a basic configuration:
```bash
# Initialize Ruly with a starter configuration
ruly init
# This creates ~/.config/ruly/profiles.yml with example profiles
# Edit this file to add your own rule sources
```
### Option 4: Use Remote Sources Only
If you don't want to maintain your own rules repository, you can use rules directly from GitHub:
```yaml
profiles:
remote-only:
description: "Rules from various GitHub sources"
sources:
# Individual files
- https://github.com/rubocop/ruby-style-guide/blob/master/README.md
- https://github.com/testdouble/standard/blob/main/docs/README.md
# Entire directories (expands to all .md files)
- https://github.com/fakecorp/standards/tree/main/ruby
- https://github.com/fakecorp/standards/tree/main/testing
```
### Example: Setting Up Like patrickclery/rules
Here's how the maintainer set up their private rules repository:
1. **Created a private repository:**
```bash
gh repo create patrickclery/rules --private --description "Private rules for Ruly gem"
```
2. **Created your rules content and pushed to GitHub**
3. **Updated your Ruly configuration:**
```yaml
# ~/.config/ruly/profiles.yml
profiles:
complete:
description: "Personal + FakeCorp rules"
sources:
- github: patrickclery/rules
branch: main
rules:
- ruby
- testing
- commands
- github: fakecorp/cursor-rules
branch: main
rules:
- workflow
- jira
```
## 📝 Using Ruly Commands
Ruly provides a powerful CLI for managing and compiling your AI assistant rules.
### Basic Commands
**Combine all rules into one file:**
```bash
ruly squash
```
**Use a specific profile:**
```bash
# Profile name as positional parameter
ruly squash rails
ruly squash api
```
**Custom output file:**
```bash
# Squash mode with custom output
ruly squash --output-file=combined-rules.md
# or using short option
ruly squash -o docs/my-rules.md
# Combine with profile
ruly squash rails -o RAILS.md
```
**Analyze token usage:**
```bash
# Analyze a specific profile
ruly analyze rails
ruly analyze api
# Analyze all profiles
ruly analyze --all
ruly analyze -a
```
**Clean up generated files:**
```bash
# Clean all agent-related files for current agent
ruly clean
# Clean files from specific profile
ruly clean rails
# Clean files for specific agent
ruly clean --agent cursor
# Dry run to see what would be deleted
ruly clean --dry-run
ruly clean -d
# Clean before squashing (remove old files first)
ruly squash --clean
ruly squash rails --clean
ruly squash -c # Short form
# Deep clean before squashing (remove ALL Claude artifacts)
ruly squash --deepclean
ruly squash rails --deepclean
```
**Generate MCP server configuration:**
```bash
# Create .mcp.json with specific servers (must exist in ~/.config/ruly/mcp.json)
ruly mcp atlassian teams playwright
# Use MCP servers from a profile
ruly mcp -r workaxle-spike
ruly mcp --profile workaxle-bug
# Append to existing .mcp.json instead of overwriting
ruly mcp playwright -a
ruly mcp --append task-master-ai
# Combine profile servers with additional servers
ruly mcp -r workaxle-bug playwright
# Append profile servers to existing config
ruly mcp -r workaxle-spike -a
```
### Subagents
Subagents allow you to generate specialized agent files that Claude can dispatch to for specific tasks. Each subagent is a self-contained agent with its own rules, commands, and MCP server access.
#### Defining Subagents in Profiles
Add a `subagents` array to any profile. Each subagent references another profile:
```yaml
profiles:
# Main profile that spawns subagents
full:
description: "Complete development environment"
files:
- /path/to/rules/core.md
subagents:
- name: bug_investigator
profile: bug
- name: test_runner
profile: testing
- name: pr_manager
profile: pr
# Profiles used by subagents
bug:
description: "Bug investigation and debugging"
files:
- /path/to/rules/bug/
- /path/to/rules/debugging.md
mcp_servers:
- task-master-ai
testing:
description: "Testing and QA workflows"
files:
- /path/to/rules/testing/
mcp_servers:
- playwright
pr:
description: "PR management"
files:
- /path/to/rules/github/pr/
```
#### How It Works
When you run `ruly squash -r full`:
1. **MCP servers collected**: Recursively collects `mcp_servers` from all subagent profiles
2. **`.mcp.json` written**: Parent's `.mcp.json` includes all collected servers (deduplicated)
3. **Main rules generated**: `CLAUDE.local.md` with the main profile content
4. **Agent files created**: `.claude/agents/{name}.md` for each subagent
5. **Commands organized**: `.claude/commands/{agent_name}/` for agent-specific commands
```
your-project/
├── CLAUDE.local.md # Main rules (from 'full' profile)
├── .mcp.json # MCP servers (parent + all subagent servers)
├── .ruly/
│ └── bin/ # Bin files (from scripts: key)
└── .claude/
├── agents/
│ ├── bug_investigator.md # Squashed 'bug' profile
│ ├── test_runner.md # Squashed 'testing' profile
│ └── pr_manager.md # Squashed 'pr' profile
├── commands/
│ ├── bug_investigator/ # Commands for bug agent
│ ├── test_runner/ # Commands for testing agent
│ └── pr_manager/ # Commands for PR agent
└── skills/ # Skills (from skills: key)
└── debugging/
└── SKILL.md
```
#### MCP Server Propagation
Claude Code subagents inherit the parent session's MCP configuration — they cannot have independent MCP servers. Ruly handles this automatically: during `ruly squash`, MCP servers from all subagent profiles (recursively, including nested subagents) are collected and merged into the parent's `.mcp.json`.
For example, given this profile configuration:
```yaml
profiles:
core:
description: "Main orchestrator"
files:
- /path/to/rules/core.md
# Note: no mcp_servers defined here
subagents:
- name: comms
profile: comms
- name: feature
profile: feature
comms:
description: "Communication agent"
files:
- /path/to/rules/comms/
mcp_servers:
- teams
- mattermost
feature:
description: "Feature development"
files:
- /path/to/rules/feature/
mcp_servers:
- Ref
```
Running `ruly squash core` produces a `.mcp.json` containing `teams`, `mattermost`, and `Ref` — all propagated from the subagent profiles — even though `core` itself defines no MCP servers. The console output shows which servers were propagated:
```
🔌 Propagated MCP servers from subagents: teams, mattermost, Ref
🔌 Updated .mcp.json with MCP servers
```
This propagation is recursive: if `comms` itself has subagents with additional MCP servers, those are collected too. Circular references are handled safely.
#### Agent File Format
Generated agent files have YAML frontmatter that Claude understands:
```yaml
---
name: bug_investigator
description: Bug investigation and debugging
tools: inherit
model: haiku # Set via subagent or profile config (default: inherit)
# Auto-generated from profile: bug
# Do not edit manually - regenerate using 'ruly squash full'
---
# Bug Investigator
Bug investigation and debugging
## Profile Content
[squashed content from bug profile]
## MCP Servers
This subagent has access to the following MCP servers:
- task-master-ai
---
*Last generated: 2026-02-04 12:30:00*
*Source profile: bug*
```
#### Model Specification
Control which Claude model each subagent uses. Route lightweight tasks (context fetching, DMs) to faster/cheaper models while keeping complex tasks on the most capable model.
##### Subagent-Level Model
Specify `model` directly on a subagent entry:
```yaml
subagents:
- name: context_grabber
profile: context-grabber
model: haiku # Fast, cheap — just fetching data
- name: core_engineer
profile: core-engineer
model: opus # Most capable — complex implementation
- name: comms
profile: comms # No model — inherits from profile or defaults to 'inherit'
```
##### Profile-Level Default Model
Set a default model for all subagents in a profile:
```yaml
profiles:
core:
description: "Main orchestrator"
model: sonnet # Default for all subagents
files:
- /path/to/rules/core.md
subagents:
- name: fast_agent
profile: fast-tasks
model: haiku # Overrides profile default
- name: smart_agent
profile: complex-tasks
# Uses profile default (sonnet)
```
##### Inheritance Chain
Model is resolved in this order:
1. **Subagent `model`** — if specified on the subagent entry
2. **Parent profile `model`** — if set on the profile containing the subagents
3. **`inherit`** — the default (inherits from the calling session)
Valid values: `haiku`, `sonnet`, `opus`, or `inherit`.
> **Note:** Skills can also specify `model` in their frontmatter — this is already supported and preserved during squash.
#### Directory Structure for Subagents
Subagent instruction files should be organized in `agents/` directories:
```
rules/
└── comms/
├── ms-teams/
│ ├── common.md # Shared patterns (loaded by both)
│ ├── commands/
│ │ └── dm.md # User command: /ms-teams:dm
│ └── agents/
│ └── ms-teams-dm.md # Subagent: dispatched on "send it"
└── mattermost/
├── common.md # Shared patterns (loaded by both)
├── commands/
│ └── dm.md # User command: /mattermost:dm
└── agents/
└── mattermost-dm.md # Subagent: dispatched on "send it"
```
**Key distinction:**
- `commands/` - User-invocable via `/command-name`
- `agents/` - Dispatched programmatically by the orchestrator
#### When to Use Subagents
| Use Case | Benefit |
|----------|---------|
| **Specialized tasks** | Each agent has focused rules for its domain |
| **Parallel work** | Dispatch multiple agents for independent tasks |
| **Context isolation** | Agents only load rules they need |
| **MCP server propagation** | Subagent MCP servers are automatically propagated to parent |
#### Example: Development Workflow
```yaml
profiles:
workaxle:
description: "Main WorkAxle development"
files:
- /path/to/rules/core.md
subagents:
- name: comms
profile: comms # Jira, Teams, GitHub communications
- name: merger
profile: merger # PR merging operations
- name: dashboard
profile: dashboard # PR status dashboard
comms:
description: "Communication via Jira, Teams, GitHub"
files:
- /path/to/rules/comms/
mcp_servers:
- teams
- atlassian
merger:
description: "PR merging commands"
files:
- /path/to/rules/github/pr/
mcp_servers: []
dashboard:
description: "Open PRs dashboard"
files:
- /path/to/rules/dashboard.md
mcp_servers: []
```
Then Claude can dispatch to these agents:
```
User: "Update all my PRs with latest main"
Claude: [Dispatches to merger agent which has PR merge rules]
User: "Send a Teams message about WA-1234"
Claude: [Dispatches to comms agent which has Teams MCP access]
User: "Show me my open PRs"
Claude: [Dispatches to dashboard agent]
```
### Profile System
Profiles allow you to define collections of rules to combine, rather than always including all files.
**List available profiles:**
```bash
ruly list-profiles
```
**Use a specific profile:**
```bash
# Use the 'core' profile
ruly squash --profile core
# Use 'testing' profile with custom output
ruly squash --profile testing -o testing-rules.md
# Short form
ruly squash -r minimal
```
#### Available Profiles
Profiles depend on having access to rule files. If you cloned with the default rules submodule, you'll have access to the profiles defined in `profiles.yml`. Otherwise, create your own profiles in `~/.config/ruly/profiles.yml` pointing to your rule sources.
- **qa** — WorkAxle QA acceptance testing. Write and run Playwright specs in the automation-test-qa repo against dev.workaxle.com. Includes skills for running acceptance tests and syncing the QA repo.
#### Custom Profiles
Create a `~/.config/ruly/profiles.yml` file to define your own profiles or override existing ones:
```yaml
# ~/.config/ruly/profiles.yml
---
tier: claude_max
profiles:
# Complete development environment combining multiple sources
my_company_core:
description: Complete development environment with Ruby, testing, and workflow rules
tier: claude_max
sources:
# John's private rules repository
- github: john/private-rules
branch: main
rules:
- rules/commands/bug
- rules/commands/pr
- rules/bug
- rules/commands.md
- rules/core
- rules/core/debugging
- rules/pr
- rules/ruby
- rules/testing
- rules/commands/testing
- rules/commands/workflow
# Company's shared rules repository
- github: my_company/development-standards
branch: main
rules:
- rules/commands/jira/details.md
- rules/workflow
- rules/jira
# Local files from various projects
development_local:
description: Auto-generated from local sources
files:
- /Users/john/Projects/my_app/rules/ruby/common.md
- /Users/john/Projects/my_app/rules/ruby/monads.md
- /Users/john/Projects/my_app/rules/ruby/rspec.md
- /Users/john/Projects/my_app/rules/ruby/sequel.md
- /Users/john/Projects/my_app/rules/testing/common.md
- /Users/john/Projects/my_app/rules/commands.md
- /Users/john/Projects/my_app/rules/commands/bug/diagnose.md
- /Users/john/Projects/my_app/rules/commands/bug/fix.md
- /Users/john/Projects/my_app/rules/commands/pr/create.md
tier: claude_max
# Simple profile for specific context
testing_only:
description: Testing and QA rules
tier: claude_max
files:
- /Users/john/Projects/my_app/rules/testing/*.md
- /Users/john/Projects/my_app/rules/commands/testing/*.md
```
#### Profile Keys: Skills, Commands, and Bins
Profiles support explicit keys for files that need special treatment. Files listed under `files:` are always squashed into the main output (`CLAUDE.local.md`) regardless of their path. To output files as skills, commands, or bins, use the dedicated keys:
```yaml
profiles:
my-profile:
description: "Example with explicit keys"
files:
# Regular rule files — squashed into CLAUDE.local.md
- /path/to/rules/core.md
- /path/to/rules/frameworks/ruby.md
skills:
# Output as .claude/skills/{name}/SKILL.md
- /path/to/rules/skills/debugging.md
- /path/to/rules/github/pr/skills/pr-review-loop.md
commands:
# Output as .claude/commands/{path}.md
- /path/to/rules/github/pr/commands/create.md
- /path/to/rules/comms/jira/commands/comment.md
scripts:
# Copied to .claude/scripts/ as executables
- /path/to/rules/bin/deploy.sh
```
**Key behavior:**
| Profile key | Output location | What it does |
|------------|----------------|--------------|
| `files:` | `CLAUDE.local.md` | Squashed into main output (always, regardless of path) |
| `skills:` | `.claude/skills/{name}/SKILL.md` | Creates individual skill files |
| `commands:` | `.claude/commands/{path}.md` | Creates slash command files |
| `scripts:` | `.claude/scripts/` | Copies scripts as executables |
All four keys support both individual file paths and directory paths. Directories are expanded:
- `skills:` and `commands:` directories expand to all `*.md` files
- `scripts:` directories expand to all `*.sh` files
**Frontmatter `skills:` references** in individual rule files still work independently. If a rule file declares `skills:` in its frontmatter, those referenced files are automatically resolved and output as SKILL.md files during squash, regardless of which profile key they appear under.
**Remote Sources:**
- Supports pulling rules directly from GitHub repositories
- Automatically converts GitHub blob URLs to raw URLs
- Non-Claude agents include all files in the main output
**GitHub URL Formats:**
- **Individual files**: Use `/blob/` URLs for specific files
- Example: `https://github.com/owner/repo/blob/branch/path/to/file.md`
- **Directories**: Use `/tree/` URLs to include all `.md` files in a directory
- Example: `https://github.com/owner/repo/tree/branch/path/to/directory`
- Automatically expands to include all markdown files in that directory
- **Important**: Files with extensions (like `.md`) in `/tree/` URLs are treated as individual files, not directories
**Command File Handling:**
- When `--agent claude` (default), files listed under the `commands:` profile key are saved to `.claude/commands/`
- For other agents, command files are included in the main output file
- Files in `/commands/` paths under `files:` are treated as regular content (squashed into main output)
**Caching:**
- Use `--cache` flag to enable caching for any profile
- Cached files are stored in `cache//` directory
- Remote files are cached separately in `cache/remote/` (7-day expiration)
- Cache is disabled by default
- Use `ruly clean` to remove cache files
User profiles:
- Are automatically loaded from `~/.config/ruly/profiles.yml`
- Override base profiles with the same name
- Are stored in your home directory configuration
- Allow user-specific or team-specific customizations
#### Profile Inheritance (`extends:`)
Profiles can extend other profiles using the `extends:` key. The child profile inherits all keys from the parent, with:
- **Array keys** (`files`, `skills`, `commands`, `scripts`, `sources`, `mcp_servers`, `omit_command_prefix`): Merged via union — parent entries first, then child entries, deduplicated
- **Scalar keys** (`description`, `model`, `tier`): Child wins — parent value only used if child doesn't define it
- **Subagents**: Merged by `name` — child entry overrides parent entry with same name
```yaml
profiles:
base:
description: "Base development profile"
files:
- rules/core.md
- rules/common.md
mcp_servers:
- task-master-ai
extended:
extends: base
description: "Extended profile with extra tools"
files:
- rules/extra.md
mcp_servers:
- playwright
```
After resolution, `extended` will have:
- `files`: `[rules/core.md, rules/common.md, rules/extra.md]`
- `mcp_servers`: `[task-master-ai, playwright]`
- `description`: `"Extended profile with extra tools"`
Multi-level inheritance is supported (A extends B extends C). Circular references are detected and produce an error.
### Commands
- **Squash** (`squash [RECIPE]`): Combines all rule content into a single large file. Profile is
optional positional parameter. Supports fetching remote GitHub files and caching for performance.
Use `--toc` or `-t` to generate a table of contents with unique anchors for all headers, ensuring proper navigation even when multiple files have identical header names. Also includes a list of available slash commands.
Use `--deepclean` to remove all Claude artifacts before squashing (overrides `--clean`).
Use `--verbose` or `-v` to show detailed per-file processing output (file paths, token counts, requires discovery). Default output shows only profile, subagents, errors, and summary.
- **Analyze** (`analyze [RECIPE]`): Analyzes token usage for profiles without generating files. Shows
detailed file breakdown and total token count. Use `--all` to analyze all profiles at once.
- **Clean** (`clean [RECIPE]`): Deletes output files created by the squash command. Profile is
optional. Removes main output file and command files directory.
Use `--deepclean` to remove all Claude artifacts (.claude/ directory, CLAUDE.local.md, CLAUDE.md) regardless of profile.
- **Introspect** (`introspect [FILE_PATH]`): Analyzes a markdown file to extract its frontmatter
metadata and identify any `requires:` dependencies. Shows the YAML frontmatter, lists required
files, and displays their resolved paths. Useful for understanding file dependencies and debugging
the requires system. If no file path is provided, it will look for a file in the current directory.
- **List Profiles** (`list-profiles`): Shows all available profiles with file counts and cache
indicators.
- **Version** (`version`): Shows the current Ruly version.
### Slash Commands
Slash commands are special commands that can be defined in your rule files to provide quick actions for AI assistants. When you include command files in your rules (typically in a `commands/` directory), they become available as slash commands in the generated output.
For example, if you have a file `commands/bug/diagnose.md` in your rules, it would become available as `/bug:diagnose` when using the generated rules with Claude or other AI assistants.
The `--toc` option will automatically generate:
1. A table of contents with links to all headers in the combined document
2. Unique anchors for headers (prefixed with the source file path) to handle duplicate header names across files
3. A list of all available slash commands in your squashed output
This ensures proper navigation even when multiple rule files contain headers with identical names (e.g., multiple files with "# Introduction" sections).
#### Available Ruly Commands
- `/ruly:compress` - Analyze markdown rules to find redundancies and make them more DRY
- `/ruly:decompose` - Decompose a markdown file into a directory using git mv (preserves history)
- `/run-acceptance-test` - Takes acceptance criteria (direct text, Jira ticket `WA-XXXX`, or PR number `PR:NNNN`), reads page objects from automation-test-qa, writes a Playwright spec, runs it, and reports results.
- `/sync-qa-repo` - Pulls latest from automation-test-qa, reports new/changed page objects, specs, and API helpers.
### Examples
```bash
# Generate CLAUDE.local.md with all rules
ruly squash
# Dry run - see what would be created without creating it
ruly squash --dry-run
ruly squash -d
# Generate core rules only
ruly squash --profile core
ruly squash -r core
# Generate squashed testing rules to a custom file
ruly squash -r testing -o test/testing-rules.md
# Generate rules for a different agent (e.g., cursor)
ruly squash -r rails --agent cursor -o CURSOR.md
ruly squash -r rails -a cursor -o CURSOR.md
# Generate with remote sources (command files go to .claude/commands/)
ruly squash -r example_mixed
# Use cached version (if profile has cache: true)
ruly squash rails
# Bypass cache for one run
ruly squash rails --no-cache
# Clean up generated files
ruly clean
# Dry run - see what would be deleted
ruly clean --dry-run
ruly clean -d
# Deep clean - remove all Claude artifacts
ruly clean --deepclean
# Clean specific output file
ruly clean -o test/testing-rules.md
# Introspect a markdown file to see its frontmatter and requires
ruly introspect rules/ruby/ruby-practices.md
# Introspect a file in the current directory
ruly introspect README.md
# List what profiles are available
ruly list-profiles
# Show version
ruly version
# View help
ruly help
ruly help squash
ruly help clean
ruly help introspect
```
Ruly will automatically:
- Load profiles from both `profiles.yml` and `~/.config/ruly/profiles.yml`
- Support glob patterns in profile definitions
- Create parent directories if using custom output paths
- Display file count and output size
- Show which profile was used in the output
## Example Recipes
### Multi-Repo Orchestrator
An orchestrator that manages multiple repositories, each with their own `CLAUDE.md` and hooks. Subagents dispatched into each repo automatically pick up the repo's configuration.
#### Directory Layout
```
~/agents/orchestrator/
├── CLAUDE.local.md # Generated orchestrator rules
├── .mcp.json # MCP servers (collected from all subagents)
├── .claude/
│ ├── agents/
│ │ ├── backend_engineer.md # Has acme-api's CLAUDE.md + hooks baked in
│ │ ├── frontend_engineer.md # Has acme-web's CLAUDE.md + rules + hooks baked in
│ │ └── comms.md # Pure ruly profile (no repo append)
│ ├── scripts/
│ │ └── worktree-create.sh # Propagated to all submodule dirs
│ └── settings.local.json # Parent hooks (WorktreeCreate)
├── acme-api/ # Backend repo (git submodule)
│ ├── CLAUDE.md # 1800-line repo-specific guidance
│ └── .claude/
│ └── settings.json # No custom hooks
├── acme-web/ # Frontend repo (git submodule)
│ ├── CLAUDE.md # 500-line repo-specific guidance
│ └── .claude/
│ ├── rules/
│ │ └── command-timeouts.md # Repo-specific rules
│ ├── hooks/
│ │ └── eslint-fix.sh # Repo-specific hook script
│ └── settings.json # PostToolUse hook for ESLint
```
#### Profile Configuration
```yaml
profiles:
orchestrator:
description: "Multi-repo dispatcher"
hooks:
WorktreeCreate:
- hooks:
- type: command
command: ".claude/scripts/worktree-create.sh"
timeout: 120
files:
- /path/to/rules/orchestrator/dispatch.md
scripts:
- /path/to/rules/orchestrator/bin/worktree-create.sh
subagents:
# Backend — reads acme-api's CLAUDE.md and hooks
- name: backend_engineer
profile: backend-engineer
cwd: acme-api
append: true
# Frontend — reads acme-web's CLAUDE.md, rules, and hooks
- name: frontend_engineer
profile: frontend-engineer
cwd: acme-web
append: true
# Comms — pure ruly profile, no repo to append
- name: comms
profile: comms
```
#### What `append: true` Does
When a subagent has both `cwd:` and `append: true`, ruly reads from the repo directory during squash:
| Source | What's read | Where it goes |
|--------|------------|---------------|
| `{cwd}/CLAUDE.md` | Repo's main guidance doc | Appended to agent body as `## Repository Context` |
| `{cwd}/.claude/rules/*.md` | Repo-specific rules | Appended to agent body as `## Repository Rules` |
| `{cwd}/.claude/settings.json` | Repo's hooks | Merged into agent frontmatter `hooks:` |
Each subagent gets only its own repo's hooks — no cross-contamination between subagents.
#### Generated Agent Frontmatter
The `frontend_engineer` subagent gets the parent's `WorktreeCreate` hook merged with the repo's `PostToolUse` hook:
```yaml
---
name: frontend_engineer
description: Frontend feature development - React/TypeScript with TDD
tools: Bash, Read, Write, Edit, Glob, Grep
model: inherit
mcpServers: "[playwright, Ref]"
permissionMode: bypassPermissions
hooks:
WorktreeCreate:
- hooks:
- type: command
command: ".claude/scripts/worktree-create.sh"
timeout: 120
PostToolUse:
- matcher: Edit|Write
hooks:
- type: command
command: ".claude/hooks/eslint-fix.sh"
# Auto-generated from profile: frontend-engineer
# Do not edit manually - regenerate using 'ruly squash orchestrator'
---
```
The `backend_engineer` subagent only gets the parent's hook (since acme-api has no custom hooks):
```yaml
---
name: backend_engineer
description: Backend feature development - Ruby/Sequel with TDD
tools: Bash, Read, Write, Edit, Glob, Grep
model: inherit
hooks:
WorktreeCreate:
- hooks:
- type: command
command: ".claude/scripts/worktree-create.sh"
timeout: 120
# Auto-generated from profile: backend-engineer
# Do not edit manually - regenerate using 'ruly squash orchestrator'
---
```
#### Generated Agent Body (append sections)
After the profile's squashed content, each subagent with `append: true` gets additional sections:
```markdown
## Profile Content
[squashed content from frontend-engineer profile]
---
## Repository Context
# CLAUDE.md
This file provides guidance for the acme-web frontend application...
## Development
- Use `yarn dev` for development server
- Use `yarn typecheck` for type checking
- Use `yarn lint --fix` for linting
---
## Repository Rules
## Command Timeouts
### Rule
Always use a **5-minute timeout** (300000ms) for:
- `yarn typecheck`
- `yarn lint`
---
*Last generated: 2026-03-06 10:43:25*
*Source profile: frontend-engineer*
```
#### With vs Without `append`
| Feature | `append: true` | No `append` |
|---------|----------------|-------------|
| Profile content | Included | Included |
| Repo CLAUDE.md | Baked into agent body | Not visible to subagent |
| Repo .claude/rules/ | Baked into agent body | Not visible to subagent |
| Repo hooks (settings.json) | Merged into frontmatter | Not applied |
| Parent hooks | Always included | Always included |
| MCP servers | From profile (propagated to parent) | From profile (propagated to parent) |
> **Note:** Claude Code subagents do **not** automatically discover `CLAUDE.md`, `.claude/rules/`, or `.claude/settings.json` from their CWD. The `append` feature exists specifically to bridge this gap by baking repo configuration into the agent file at squash time.
---
## 🔧 Troubleshooting
### Common Issues
**Permission denied:**
- Ensure you have write access to your project directory
- Check that Ruby gems can be installed globally
**Profile not found:**
- Run `ruly list-profiles` to see available profiles
- Check `~/.config/ruly/profiles.yml` for user-defined profiles
- Ensure profile names match exactly (case-sensitive)
**Files not being cleaned:**
- Use `ruly clean --dry-run` to preview what will be deleted
- Specify agent with `--agent` option if not using Claude
- Ensure you're using the correct profile name if specified