Rules
The rules section of your capabilities file installs short, focused instruction documents into each provider's native rules system: .cursor/rules/*.mdc, .windsurf/rules/*.md, .github/instructions/*.instructions.md, and so on. For providers without a dedicated rules directory (Claude Code, Codex, OpenCode, etc.), CAPA folds the same rule content into the project's agent instructions file (AGENTS.md or CLAUDE.md) as a managed marker block.
Rules work well for project conventions the agent should always see: commit message style, code review checklists, "run lints before claiming success", architecture decisions, glossaries.
How CAPA Installs Rules
On every capa install, CAPA resolves each rule's content (inline, remote URL, or GitHub/GitLab repo), then writes it once per active provider using the provider's native format:
| Provider | Output | Frontmatter fields |
|---|---|---|
cursor | .cursor/rules/{id}.mdc | description, globs, alwaysApply |
windsurf | .windsurf/rules/{id}.md | description, globs, trigger (always_on / model_decision) |
github-copilot | .github/instructions/{id}.instructions.md | applyTo |
Everything else (claude-code, codex, opencode, amp, gemini-cli, cline, etc.) | Folded into AGENTS.md or CLAUDE.md as a <!-- capa:start:rule:{id} --> block | n/a |
Subsequent installs upsert changed rules and prune rules you removed from the capabilities file (deleting the file for directory-based providers, removing the marker block for instruction-folded providers). Files you authored by hand in those directories are never touched. CAPA only manages files it wrote itself.
Rule Types
Rules use the same four source types as skills, but resolve to a single file (no SKILL.md directory).
1. Inline Rules
Embed the rule body directly in the capabilities file:
rules:
- id: commit-style
type: inline
description: How to write commit messages in this repo
appliesTo:
- "**/*"
alwaysApply: true
content: |
Always use Conventional Commits:
feat: new feature
fix: bug fix
docs: docs-only change
chore: build / tooling / housekeeping
Subject line must be <= 72 chars, imperative mood,
no trailing period.
{
"rules": [
{
"id": "commit-style",
"type": "inline",
"description": "How to write commit messages in this repo",
"appliesTo": ["**/*"],
"alwaysApply": true,
"content": "Always use Conventional Commits:\n feat: new feature\n fix: bug fix\n docs: docs-only change\n chore: build / tooling / housekeeping\n\nSubject line must be <= 72 chars, imperative mood,\nno trailing period."
}
]
}
2. Remote Rules
Fetch the rule body from any HTTP(S) URL. Useful for public rule libraries.
rules:
- id: typescript-conventions
type: remote
description: Team TypeScript conventions
appliesTo:
- "**/*.ts"
- "**/*.tsx"
url: https://example.com/rules/typescript.md
{
"rules": [
{
"id": "typescript-conventions",
"type": "remote",
"description": "Team TypeScript conventions",
"appliesTo": ["**/*.ts", "**/*.tsx"],
"url": "https://example.com/rules/typescript.md"
}
]
}
3. GitHub Rules
Fetch a rule from a GitHub repo. Uses the same @ / :: repo-string grammar as skills, with optional :version or #sha pinning, and writes its resolved commit SHA to capabilities.lock.
rules:
# Recursive search by filename
- id: code-review
type: github
description: Code review checklist
def:
repo: my-org/agent-rules@code-review.md
# Exact path inside the repo
- id: arch-decisions
type: github
description: How we make ADRs
def:
repo: my-org/standards::rules/architecture-decisions.md
# Pinned to a tag
- id: security-checklist
type: github
def:
repo: my-org/standards::rules/security.md:v2.0.0
{
"rules": [
{
"id": "code-review",
"type": "github",
"description": "Code review checklist",
"def": { "repo": "my-org/agent-rules@code-review.md" }
},
{
"id": "arch-decisions",
"type": "github",
"description": "How we make ADRs",
"def": { "repo": "my-org/standards::rules/architecture-decisions.md" }
},
{
"id": "security-checklist",
"type": "github",
"def": { "repo": "my-org/standards::rules/security.md:v2.0.0" }
}
]
}
Search vs exact: the @<name> form matches a file whose basename equals <name> (errors on 0 or multiple matches). The ::<path> form reads exactly that path. See the repo-string reference on the Skills page for full grammar details.
4. GitLab Rules
Identical to GitHub, but with the gitlab: source type. Nested groups are supported in the repo path.
rules:
- id: code-review
type: gitlab
def:
repo: mygroup/subgroup/agent-rules@code-review.md
{
"rules": [
{
"id": "code-review",
"type": "gitlab",
"def": { "repo": "mygroup/subgroup/agent-rules@code-review.md" }
}
]
}
Rule Fields
Field Type Description id string (required) Unique identifier. Used as the filename stem (e.g. {id}.mdc) and as the capa marker id when folded into AGENTS.md. type 'inline' | 'remote' | 'github' | 'gitlab' How the rule body is sourced. content string Literal body (required when type: inline). url string Raw URL (required when type: remote). def.repo string Repo-string (required when type: github or gitlab). Same grammar as skills. description string Short description. Emitted into frontmatter for Cursor and Windsurf (description field). appliesTo string[] Glob patterns for auto-attached rules. Emitted as globs for Cursor and Windsurf, and as applyTo for GitHub Copilot. alwaysApply boolean When true, the rule is always loaded regardless of file context. Maps to alwaysApply: true for Cursor and trigger: always_on for Windsurf. providers string[] Optional. Restrict the rule to specific providers (e.g. ["cursor", "windsurf"]). When omitted, applies to every active provider.
Per-Provider Frontmatter Mapping
The same Rule object produces different frontmatter for different providers. CAPA does the translation for you.
Cursor (.cursor/rules/{id}.mdc)
---
description: Code review checklist
globs:
- "**/*.ts"
- "**/*.tsx"
alwaysApply: false
---
(rule body here)
Windsurf (.windsurf/rules/{id}.md)
---
description: Code review checklist
globs:
- "**/*.ts"
- "**/*.tsx"
trigger: model_decision # or "always_on" when alwaysApply: true
---
(rule body here)
GitHub Copilot (.github/instructions/{id}.instructions.md)
---
applyTo:
- "**/*.ts"
- "**/*.tsx"
---
(rule body here)
Claude Code / Codex / OpenCode (folded into AGENTS.md or CLAUDE.md)
<!-- capa:start:rule:code-review -->
(rule body here, no frontmatter)
<!-- capa:end:rule:code-review -->
The marker comments are invisible in rendered Markdown and cheap to ignore for LLMs. CAPA uses them to upsert and prune the block on subsequent installs without touching content you wrote by hand around it.
Restricting Rules to Specific Providers
Use providers when a rule only makes sense for a subset of agents:
rules:
# Only Cursor sees this rule
- id: cursor-only-style
type: inline
providers:
- cursor
content: |
Use Cursor's auto-fix on every save.
# Cursor + Windsurf
- id: ide-shortcuts
type: inline
providers:
- cursor
- windsurf
content: |
Prefer keyboard navigation over mouse.
# No providers field → applies to every active provider
- id: universal-style
type: inline
content: |
Use 2-space indentation.
{
"rules": [
{
"id": "cursor-only-style",
"type": "inline",
"providers": ["cursor"],
"content": "Use Cursor's auto-fix on every save."
},
{
"id": "ide-shortcuts",
"type": "inline",
"providers": ["cursor", "windsurf"],
"content": "Prefer keyboard navigation over mouse."
},
{
"id": "universal-style",
"type": "inline",
"content": "Use 2-space indentation."
}
]
}
Per-provider filtering is honored during install and prune: removing cursor from the providers array of a rule will delete the corresponding .cursor/rules/{id}.mdc file on the next install.
Security Checks
The same options.security checks that apply to skills are applied to every rule body: blockedPhrases stops the install if a forbidden phrase appears, and allowedCharacters sanitizes content during installation. See the Capabilities File - security options for configuration details.
Lifecycle
- Add a rule to
capabilities.{yaml,json}. - Run
capa install. CAPA fetches the body (for remote / github / gitlab rules), applies security checks, and writes the rule into each applicable provider. - Edit the rule. The next
capa install upserts the file or marker block for you. No manual cleanup needed. - Remove the rule from the capabilities file. The next
capa install prunes the orphan file (directory-based providers) or marker block (instruction-folded providers) automatically. capa clean removes every capa-managed rule artifact across providers.
Best Practices
- Keep rules short and focused. One topic per rule. Long rules tend to be ignored.
- Use
appliesTo globs to scope rules to file types (TypeScript, Python, infra). Cursor and Windsurf auto-attach rules based on this. - Use
alwaysApply: true sparingly. Reserve it for repo-wide invariants (commit style, branch naming). - Store team-wide rules in a shared repo and reference them via
type: github. Pin to a tag so updates roll out intentionally. - Commit
capabilities.lock so the resolved commit SHA of remote rules is reproducible across teammates and CI.
Related Documentation
- Capabilities File: where the
rules section lives. - Agent Instructions: where rules are folded for providers without a rules directory.
- Skills: same repo-string grammar (
@ and ::, version or SHA pinning). - Lockfile: records the resolved SHA for rules with remote sources.
- capa install: installs and prunes rules on every run.
- capa clean: removes all capa-managed rule files and marker blocks.