| name | engineer-rule |
| description | Guide for creating persistent AI rules (coding standards, project conventions, file-specific patterns). Use when users want to create a rule, add coding standards, set up project conventions, configure file-specific patterns, or ask about rules placement. Works across IDEs (Cursor, Claude Code, OpenCode). |
| license | Based on https://github.com/anthropics/skills |
Rule Creator
This skill guides through creating persistent rules — instructions that automatically apply to AI agent sessions, enforcing coding standards, project conventions, and file-specific patterns.
About Rules
Rules are markdown files with metadata that provide persistent context to AI agents. They differ from skills in that rules are automatically injected into every relevant session without explicit invocation.
Rules serve two purposes:
- Always-apply rules — universal standards for every conversation (coding style, architecture decisions, project conventions)
- Conditional rules — file-specific patterns triggered when matching files are open (TypeScript conventions for
*.ts, React patterns for *.tsx)
IDE Detection and Rule Placement
Rules work across multiple IDEs but use different file formats and locations. Before creating a rule, determine the current environment.
Control Primitives Map by IDE
| Primitive | Scope | Claude Code | Cursor | OpenCode |
|---|
| Persistent Instructions | User | ~/.claude/CLAUDE.md | - | ~/.config/opencode/AGENTS.md
~/.claude/CLAUDE.md (fallback) |
| Project | CLAUDE.md
.claude/rules/*.md | AGENTS.md
.cursor/rules/*/RULE.md
.cursor/rules/*.mdc | AGENTS.md
CLAUDE.md (fallback)
opencode.json instructions |
| Folder | subdir/CLAUDE.md
CLAUDE.local.md | subdir/AGENTS.md | - |
| Conditional Instructions | Project | .claude/rules/*.md | .cursor/rules/*/RULE.md
.cursor/rules/*.mdc | opencode.json instructions (globs) |
| Custom Commands | User | ~/.claude/commands/*.md | ~/.cursor/commands/*.md | ~/.config/opencode/commands/*.md |
| Project | .claude/commands/*.md
.claude/commands/<namespace>/*.md | .cursor/commands/*.md | .opencode/commands/*.md |
| Event Hooks | User | ~/.claude/settings.json | ~/.cursor/hooks.json | ~/.config/opencode/plugins/*.{js,ts} |
| Project | .claude/settings.json
.claude/settings.local.json | .cursor/hooks.json | .opencode/plugins/*.{js,ts} |
| MCP Integration | User | settings.json
managed-mcp.json | ~/.cursor/mcp.json | opencode.json mcp |
| Project | .mcp.json | .cursor/mcp.json | opencode.json mcp |
| Context Ignoring | User | .claude/settings.json | - | - |
| Project | - | .cursorignore | .gitignore
.ignore
opencode.json watcher.ignore |
Rule-Specific Paths
| IDE | Always-Apply Rules | Conditional Rules | Format |
|---|
| Cursor | .cursor/rules/*/RULE.md with alwaysApply: true | .cursor/rules/*/RULE.md with globs: | YAML frontmatter + Markdown |
| Claude Code | CLAUDE.md, .claude/rules/*.md (no paths: frontmatter) | .claude/rules/*.md with paths: (array of globs). description accepted but does not scope. globs:/alwaysApply ignored. Triggers on Read only, not Write/Edit. Subdirs discovered recursively. | YAML frontmatter (paths, optional description) + Markdown |
| OpenCode | AGENTS.md, opencode.json instructions | opencode.json instructions (globs) | AGENTS.md: Plain Markdown; opencode.json: JSON array of paths/globs/URLs |
Detection Strategy
- Check for IDE-specific markers in the project:
.cursor/ directory -> Cursor
.claude/ directory -> Claude Code
.opencode/ directory or opencode.json -> OpenCode
- If multiple detected or none -> ask the user
- Ask: always-apply or conditional (file-specific)?
Gather Requirements
Before creating a rule, determine:
- Purpose: What should this rule enforce or teach?
- Scope: Always apply, or only for specific files?
- File patterns: If conditional, which glob patterns? (e.g.,
**/*.ts, backend/**/*.py)
Inferring from Context
If prior conversation context exists, infer rules from what was discussed. Create multiple rules if the conversation covers distinct topics. Don't ask redundant questions if context provides answers.
Required Questions
If scope not specified:
- "Should this rule always apply, or only when working with specific files?"
If file-specific but no concrete patterns:
- "Which file patterns should this rule apply to?"
Rule Format by IDE
Cursor
Directory-based rules in .cursor/rules/<rule-name>/RULE.md:
---
description: Brief description of what this rule does
globs: "**/*.ts"
alwaysApply: false
---
# Rule Title
Rule content here...
Legacy format (.cursor/rules/*.mdc) still works but is deprecated. Prefer directory format.
| Field | Type | Description |
|---|
description | string | What the rule does (used for agent discovery when alwaysApply: false) |
globs | string | File pattern — rule applies when matching files are in context |
alwaysApply | boolean | If true, applies to every session regardless of files |
Claude Code
Rules in .claude/rules/*.md (subdirectories discovered recursively). Frontmatter fields: paths (array of glob strings), description (optional, informational only — does NOT scope the rule). Cursor-specific fields (globs, alwaysApply) are silently ignored (rule becomes always-apply).
Conditional rule (loads when Claude reads a matching file):
---
paths:
- "src/**/*.ts"
---
# Rule Title
Rule content here...
Multiple glob patterns:
---
paths:
- "src/**/*.ts"
- "lib/**/*.{ts,tsx}"
- "tests/**/*.test.ts"
---
Always-apply rule: omit paths frontmatter entirely, or use CLAUDE.md (project root / subdirectory).
Limitations: paths: triggers on Read only — Write/Edit to a matching path without prior Read does NOT load the rule.
OpenCode
Always-apply rules in AGENTS.md (project root, plain markdown):
# Rule Title
Rule content here...
Or via opencode.json field instructions (array of paths, globs, or URLs):
{
"instructions": [
"AGENTS.md",
".cursor/rules/**/*.md",
"https://example.com/standards.md"
]
}
Global user rules: ~/.config/opencode/AGENTS.md. Falls back to ~/.claude/CLAUDE.md unless OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1.
Core Principles
Keep Rules Concise
- Under 50 lines preferred, max 500 lines
- One concern per rule: split large rules into focused pieces
- Actionable: write like clear internal docs
- Concrete examples: show good/bad patterns with code
Structure
Every rule should contain:
- Clear title — what aspect it covers
- Brief context — why this rule exists (1-2 sentences max)
- The rules themselves — concrete, actionable instructions
- Examples — good/bad code patterns when applicable
Naming
- Cursor: directory name =
kebab-case (e.g., typescript-standards/RULE.md)
- Claude Code: filename =
kebab-case.md (e.g., typescript-standards.md)
- Others: section heading in the shared file
Rule Creation Process
Phase 1: Discovery
- Determine IDE (auto-detect or ask)
- Determine scope (always-apply vs conditional)
- Determine file patterns if conditional
- Gather the actual standards/conventions to encode
Phase 2: Implementation
- Create the rule file in the correct location for the detected IDE
- Write frontmatter with appropriate fields
- Write concise, actionable rule content
- Include concrete code examples (good/bad patterns)
Phase 3: Verification
Run validation:
deno run -A scripts/validate_rule.ts <path/to/rule-file-or-directory>
Checklist:
Common Rule Categories
| Category | Scope | Example Patterns |
|---|
| Coding standards | Always or per-language | Error handling, naming, imports |
| Architecture | Always | Layer boundaries, dependency rules |
| Framework patterns | File-specific | React components, API routes |
| Testing | File-specific | Test structure, mocking conventions |
| Documentation | File-specific | JSDoc format, comment standards |
| Security | Always | Auth patterns, input validation |
Example Rules
Error Handling (TypeScript) — Cursor
---
description: TypeScript error handling standards
globs: "**/*.ts"
alwaysApply: false
---
# Error Handling
Always use typed errors with context:
\`\`\`typescript
// BAD
try {
await fetchData();
} catch (e) {}
// GOOD
try {
await fetchData();
} catch (e) {
logger.error('Failed to fetch', { error: e });
throw new DataFetchError('Unable to retrieve data', { cause: e });
}
\`\`\`
Error Handling (TypeScript) — Claude Code
---
paths:
- "**/*.ts"
---
# Error Handling
Always use typed errors with context:
\`\`\`typescript
// BAD
try {
await fetchData();
} catch (e) {}
// GOOD
try {
await fetchData();
} catch (e) {
logger.error('Failed to fetch', { error: e });
throw new DataFetchError('Unable to retrieve data', { cause: e });
}
\`\`\`
React Patterns — Cursor
---
description: React component patterns
globs: "**/*.tsx"
alwaysApply: false
---
# React Patterns
- Use functional components
- Extract custom hooks for reusable logic
- Colocate styles with components
- Props interface named `{ComponentName}Props`
React Patterns — Claude Code
---
paths:
- "**/*.tsx"
- "**/*.jsx"
---
# React Patterns
- Use functional components
- Extract custom hooks for reusable logic
- Colocate styles with components
- Props interface named `{ComponentName}Props`
Project Architecture (Always Apply) — Cursor
---
description: Core architecture rules
alwaysApply: true
---
# Architecture
- Domain logic in `src/domain/` — no framework imports
- API handlers in `src/api/` — thin, delegate to domain
- Shared types in `src/types/` — no runtime code
Project Architecture (Always Apply) — Claude Code
# Architecture
- Domain logic in `src/domain/` — no framework imports
- API handlers in `src/api/` — thin, delegate to domain
- Shared types in `src/types/` — no runtime code