portable-skills-and-rules
Defines SKILL.md structure, valid frontmatter fields, and cross-tool setup for Claude Code, Cursor, OpenCode, and Cline. ALWAYS read before creating or editing any SKILL.md file. This skill should be used when "writing a skill", "creating a skill", "editing a skill", "skill frontmatter", "SKILL.md format", "AGENTS.md", "CLAUDE.md", or setting up skills across multiple AI tools.
Best use case
portable-skills-and-rules is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Defines SKILL.md structure, valid frontmatter fields, and cross-tool setup for Claude Code, Cursor, OpenCode, and Cline. ALWAYS read before creating or editing any SKILL.md file. This skill should be used when "writing a skill", "creating a skill", "editing a skill", "skill frontmatter", "SKILL.md format", "AGENTS.md", "CLAUDE.md", or setting up skills across multiple AI tools.
Teams using portable-skills-and-rules should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/portable-skills-and-rules/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How portable-skills-and-rules Compares
| Feature / Agent | portable-skills-and-rules | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Defines SKILL.md structure, valid frontmatter fields, and cross-tool setup for Claude Code, Cursor, OpenCode, and Cline. ALWAYS read before creating or editing any SKILL.md file. This skill should be used when "writing a skill", "creating a skill", "editing a skill", "skill frontmatter", "SKILL.md format", "AGENTS.md", "CLAUDE.md", or setting up skills across multiple AI tools.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Cross-Tool Interoperability
Write skills, rules, and commands that work across Claude Code, OpenCode, Cursor, and Cline without duplication.
## Quick Start
All four tools canonically search `.claude/skills/` per the spec. However, Cursor has several bugs that require a workaround — see [Cursor Bugs](#cursor-bugs) below.
**In practice, always write new skills to `.cursor/skills/` and symlink `.claude/skills/` to it:**
```bash
# One-time setup per project
ln -sfn ../.cursor/skills .claude/skills
```
Skills use combined frontmatter that each tool reads selectively:
```yaml
---
name: my-skill
description: "Does X. Use when user asks to Y or mentions Z."
user-invocable: true
disable-model-invocation: false
---
```
Always set both invocation fields explicitly for visible defaults across all tools.
## Core Strategy
### Skills: Fully Shareable
The spec says `.claude/skills/` is the canonical location. In practice, Cursor bugs (see below) require the physical files to live in `.cursor/skills/`, with `.claude/skills/` as a symlink.
**Always write new skills to `.cursor/skills/`.** The symlink makes Claude Code and other tools pick them up automatically.
Create one SKILL.md with combined frontmatter. Each tool reads what it understands, ignores the rest.
**Notes**:
- `.cursor/skills/` holds the physical files — always write here
- `.claude/skills/` is a symlink to `.cursor/skills/` — never write directly to it
- Cline skills require enabling in Settings → Features → Enable Skills (experimental)
- Skills can be invoked via `/<skill-name>` slash commands in Claude Code, Cursor IDE, and Cursor CLI
### Cursor Bugs
Cursor has three known issues that drive the `.cursor/skills/` workaround:
1. **Doesn't search `.claude/skills/`** — Despite the spec, Cursor IDE does not reliably read skills from `.claude/skills/`. It only reliably finds skills in `.cursor/skills/`.
2. **Doesn't traverse above the open directory** — Cursor only searches for skills within the directory the IDE is opened to. It won't walk up to the git root. In a monorepo where the IDE is opened to a sub-project, skills defined at the repo root are invisible. **Workaround**: symlink the `.cursor/` directory into each sub-project that needs access.
3. **Skills don't survive two symlinks** — If `.claude/skills/` is a symlink and the skills inside are themselves symlinks (e.g., pointing up to a parent directory), Cursor fails to read them. Skills must be physically present at the resolved path, with at most one level of symlink indirection.
**Consequence**: Skills must be physically in `.cursor/skills/`. The symlink goes in the other direction: `.claude/skills/` → `.cursor/skills/`.
### Rules: Symlink Between Names
Claude Code uses `CLAUDE.md`. OpenCode, Cursor, and Cline use `AGENTS.md`. Content is identical—only the filename differs.
```bash
# Project level: pick one as source, symlink the other
ln -s AGENTS.md CLAUDE.md # or vice versa
# Global level
ln -s ~/dotfiles/AGENTS.md ~/.claude/CLAUDE.md
ln -s ~/dotfiles/AGENTS.md ~/.config/opencode/AGENTS.md
```
Cline also supports a `.clinerules/` folder with multiple rule files. For portability, use `AGENTS.md`.
### Cursor Rules Bug: `.mdc` Extension Required
Cursor currently only detects `.mdc` files in `.cursor/rules/`, not `.md` files, despite documentation stating both formats are supported. This breaks the symlink strategy for modular rules.
**Temporary workaround (until bug is fixed):**
- Maintain separate `.cursor/rules/*.mdc` files alongside `.claude/rules/*.md`
- Keep content synchronized between the two (manually or via script)
- Use identical frontmatter (Claude reads `paths:`, Cursor reads `globs:`, both ignore unknown keys)
- When Cursor fixes the bug, delete `.cursor/rules/*.mdc` and replace with symlink: `.cursor/rules/` → `.claude/rules/`
**Note**: This only affects modular rules in `.cursor/rules/`. Root-level `AGENTS.md` works fine in Cursor without needing `.mdc` extension.
### Claude Code Rules Extensions
Claude Code supports several rules features beyond basic `CLAUDE.md`. These are Claude Code-only but degrade gracefully (other tools simply ignore them).
**CLAUDE.local.md** — Personal project-specific preferences. Auto-added to `.gitignore`. Place next to `CLAUDE.md` for private overrides (sandbox URLs, test data, personal workflow notes).
**CLAUDE.md imports** — Use `@path/to/file` syntax to import other files into CLAUDE.md:
```markdown
See @README for project overview and @docs/git-workflow.md for git conventions.
```
Relative paths resolve from the importing file. Recursive imports supported (max depth 5). Other tools see `@path` as literal text—harmless but not functional.
**Modular rules with `.claude/rules/`** — Split rules into focused files:
```
.claude/rules/
├── code-style.md # Unconditional: always loaded
├── testing.md
└── api-design.md # Can use paths: frontmatter for file-scoped rules
```
All `.md` files load automatically. Rules can be scoped to specific files via `paths` frontmatter with glob patterns. Cursor (`.cursor/rules/` with `globs`) and Cline (`.clinerules/` with `paths`) have similar systems but use their own directories — these are not portable across tools.
**Cursor bug**: Cursor currently requires `.mdc` extension for rules in `.cursor/rules/`, not `.md`. See [Cursor Rules Bug](#cursor-rules-bug-mdc-extension-required) section.
### Commands: Use Skills Instead
Claude Code has merged commands into skills — `.claude/commands/` files still work but skills take precedence if names collide. For maximum portability, write skills instead of commands. They work as:
- Slash commands in Claude Code, Cursor IDE, and Cursor CLI (`/<skill-name>`)
- Auto-discovered capabilities in OpenCode and Cline
**Migration**: Cursor 2.4+ includes `/migrate-to-skills` to convert existing commands to skills with `disable-model-invocation: true`.
Cline has a separate "workflows" system (`.clinerules/workflows/`), but skills are more portable.
### OpenCode: Command Wrappers for Slash Invocation
OpenCode skills are NOT slash-invocable — they are loaded on-demand by the agent via the `skill` tool. To get `/skill-name` slash invocation in OpenCode, **create a thin command wrapper** that tells the agent to load the skill.
Place command wrappers in `.opencode/commands/` (project) or `~/.config/opencode/commands/` (global):
```markdown
<!-- .opencode/commands/my-skill.md -->
---
description: Short description of what the skill does
---
Load the `my-skill` skill and follow its instructions. $ARGUMENTS
```
The filename becomes the command name (e.g., `my-skill.md` → `/my-skill`). The agent receives the prompt, calls the `skill` tool to load the SKILL.md content, and follows it.
**When creating a new skill, ALWAYS create a matching OpenCode command wrapper.** If commands are symlinked between `~/.claude/commands/` and `~/.config/opencode/commands/`, one file serves both Claude Code (as a command) and OpenCode (as a slash command).
**Key differences from skills:**
- Commands support `$ARGUMENTS` and positional args (`$1`, `$2`)
- Commands support `!`command`` for shell output injection
- Commands support `@filename` for file content inclusion
- Commands can specify `agent:` and `model:` overrides in frontmatter
## Writing Portable Skills
### Required Fields (All Tools)
| Field | Requirements |
|-------|-------------|
| `name` | 1-64 chars, lowercase, hyphens only, must match folder name, pattern: `^[a-z0-9]+(-[a-z0-9]+)*$` |
| `description` | Max 1024 chars, third person, include trigger phrases |
| `user-invocable` | Always set to `true` (Claude Code: show in slash menu) |
| `disable-model-invocation` | Always set to `false` (Cursor: allow auto-discovery) |
### Invocation Control Fields (Required)
**Always set both fields explicitly** for visible defaults. All skills should be user-invokable and auto-discoverable:
```yaml
user-invocable: true # Claude Code: show in slash menu
disable-model-invocation: false # Cursor: allow auto-discovery
```
| Field | Tool | Value | Effect |
|-------|------|-------|--------|
| `user-invocable: true` | Claude Code | Required | Show in slash menu, allow `/<skill-name>` |
| `disable-model-invocation: false` | Cursor | Required | Allow auto-discovery based on description |
**Note**: These fields have opposite semantics but setting both explicitly ensures consistent behavior:
- Claude Code reads `user-invocable`, ignores `disable-model-invocation`
- Cursor reads `disable-model-invocation`, ignores `user-invocable`
- OpenCode and Cline ignore both (auto-discover via `skill` tool; for slash commands in OpenCode, use command wrappers)
### Optional Fields (Include Only When Specified)
Do not add these fields by default. Only include when the user explicitly requests them:
- `allowed-tools` - Restricts tool access (Claude Code, experimental in Cursor)
- `license` - Software license (informational, recognized by Cursor + OpenCode)
- `metadata` - Author, version info (informational, recognized by Cursor + OpenCode)
- `compatibility` - Environment requirements (recognized by Cursor + OpenCode)
These fields degrade gracefully—tools ignore what they don't recognize.
**Example with all possible fields** (only add what you need):
```yaml
---
name: review-code
description: "Reviews code for quality and bugs. Use when asked to review changes."
# === REQUIRED: Invocation control (always set explicitly) ===
user-invocable: true # Claude Code: show in slash menu
disable-model-invocation: false # Cursor: allow auto-discovery
# === OPTIONAL: Add only when specified ===
# Shared (Cursor + OpenCode + Agent Skills spec)
license: MIT
compatibility: "requires git"
metadata:
author: your-name
version: 1.0.0
# Claude Code + Cursor (experimental)
allowed-tools: Read, Grep, Glob
# Claude Code only
model: claude-sonnet-4-20250514
context: fork
agent: Explore
argument-hint: "[file-or-directory]"
---
```
### File Structure
Use the same structure across all tools:
```
skill-name/
├── SKILL.md # Required: instructions + combined frontmatter
├── scripts/ # Optional: executable code agents can run
├── references/ # Optional: detailed docs (loaded on-demand)
├── examples/ # Optional: usage examples
└── assets/ # Optional: templates, images, data files (Cursor)
```
## Setting Up Global Interoperability
Physical skills live in `.cursor/skills/`. All other tool locations symlink to it.
```bash
# Skills: physical files in .cursor/skills
mkdir -p ~/.cursor/skills
# Claude Code: symlink .claude/skills → .cursor/skills
ln -sfn ~/.cursor/skills ~/.claude/skills
# OpenCode: symlink to .cursor/skills
ln -sfn ~/.cursor/skills ~/.config/opencode/skills
# Cline: symlink to .cursor/skills
mkdir -p ~/.cline
ln -sfn ~/.cursor/skills ~/.cline/skills
# Rules: single source of truth
ln -sf ~/dotfiles/AGENTS.md ~/.claude/CLAUDE.md
ln -sf ~/dotfiles/AGENTS.md ~/.config/opencode/AGENTS.md
```
For project-level skills in a monorepo, symlink `.cursor/` into each sub-project so Cursor can find it (it won't traverse above the open directory):
```bash
# In each sub-project that needs access to skills
ln -sfn ../.cursor .cursor # if sub-project is one level deep
ln -sfn ../.cursor/skills .claude/skills
```
See [scripts/setup-interop.sh](scripts/setup-interop.sh) for full automation.
## Hard Limitations
| Limitation | Impact | Workaround |
|------------|--------|------------|
| `hooks`, `context`, `agent` | Claude Code only | Degrade gracefully |
| `allowed-tools` | Claude Code + Cursor (experimental) | Degrade gracefully in OpenCode/Cline |
| `` !`command` `` dynamic injection | Claude Code skills + OpenCode commands | Appears as literal text in Cursor/Cline |
| `$ARGUMENTS` expansion | Claude Code + OpenCode expand | Cursor/Cline show unexpanded |
| Positional arg indexing | Claude Code: 0-based (`$0`, `$1`); OpenCode: 1-based (`$1`, `$2`) | Avoid positional args in portable skills |
| `${CLAUDE_SESSION_ID}` | Claude Code only | Other tools show unexpanded |
| `/<skill-name>` invocation | Claude Code + Cursor (IDE & CLI) | OpenCode: create command wrapper (see above). Cline: auto-discovery only |
| `@path` imports in CLAUDE.md | Claude Code only | Other tools see literal `@path` text |
| `CLAUDE.local.md` | Claude Code only | Other tools ignore it; no equivalent |
| File-scoped rules | Claude Code (`paths`), Cursor (`globs`), Cline (`paths`) — each in own rule dir | Not portable across tools; use tool-specific rule dirs |
| Cursor `.md` rules bug | Cursor only detects `.mdc` in `.cursor/rules/`, not `.md` | Duplicate rules as `.mdc` until bug fixed |
| Cline skills experimental | Must enable in settings | Toggle in Settings → Features |
| Cline `.clinerules/` folder | Cline-specific rules system | Use `AGENTS.md` for portability |
| Cline global skill precedence | Global overrides project skills | Use unique names across locations |
## Validation Checklist
Before finalizing a portable skill:
- [ ] `name` is lowercase with hyphens only, matches folder name
- [ ] `description` is under 1024 chars, third person
- [ ] `description` includes trigger phrases
- [ ] `user-invocable: true` is set explicitly
- [ ] `disable-model-invocation: false` is set explicitly
- [ ] SKILL.md body uses imperative form
- [ ] No tool-specific features in core logic
- [ ] Tool-specific frontmatter clearly commented
- [ ] OpenCode command wrapper created (if slash invocation needed)
- [ ] Tested in target tools
## References
### Tool-Specific Documentation
- **[references/claude-code.md](references/claude-code.md)** - Claude Code configuration and capabilities
- **[references/opencode.md](references/opencode.md)** - OpenCode configuration and capabilities
- **[references/cursor.md](references/cursor.md)** - Cursor configuration and capabilities
- **[references/cline.md](references/cline.md)** - Cline configuration and capabilities
### Examples and Scripts
- **[examples/universal-skill.md](examples/universal-skill.md)** - Complete portable skill template
- **[scripts/setup-interop.sh](scripts/setup-interop.sh)** - Automated setup scriptRelated Skills
using-skills
Provides sub agents important information on how to use skills
use-skills-npm-package
CLI tool for discovering, installing, and managing reusable agent skills across multiple coding agents. Enables efficient skill discovery from repositories, local sources, and community repositories. Essential resource for discovering new Flutter/Dart skills.
tooluniverse-install-skills
Detect and auto-install missing ToolUniverse research skills by checking common client skill directories and cloning from GitHub if absent. Use when ToolUniverse specialized skills are not installed, when setting up a new project, or when the tooluniverse router skill needs to bootstrap its sub-skills before routing.
sync-skills
Use when syncing skills from local folders, GitHub URLs, or skillsmp.com pages to multiple AI coding tool directories
sync-rules
Synchronize shared rules into agent context files and headers.
skills-scaffolding
Guide for creating effective Claude Code skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
self-learning-skills
Memory sidecar for agent work: recall before tasks, record learnings after tasks, review recommendations, optional backport bundles.
sc-pull-request-skills
GitHub PR workflow automation including fetching unresolved comments, resolving review threads, and parallel comment resolution. Use this skill when working with PR reviews, addressing reviewer feedback, or automating PR comment workflows.
reflect-codex-skills
Generate reflections for past Codex session histories using the Reflection CLI. Use when asked to summarize or reflect on previous Codex conversations, list projects/sessions, filter by date or session id, or refresh cached reflections from ~/.codex/sessions.
publishing-rules
Rules for publishing Chrome extensions to the Chrome Web Store, ensuring proper submission guidelines are followed.
install-rules
Install rules from this project or a specified Git repo into Cursor or Trae IDE. Use when the user wants to add project/global rules to their editor from ai-cortex rules/ or another repository.
hap-skills-updater
HAP Skills Collection 技能更新和维护技能。当用户提到"更新技能"、"维护技能"、"更新 hap-skills"、"更新 skill"等需求时使用。帮助用户更新和维护 HAP Skills Collection 中的 4 个核心技能。