# Client formats: where skills live and how each client loads them

Read this when listing installed skills (Inputs), choosing a name and keys (step 4), adding a command (step 5), packaging (step 8), or answering any client-specific question. Every fact was checked on 2026-11-01 against the pages listed in `sources.yaml`, and each client's skills, permissions and configuration pages were reopened on 2026-11-06. Version numbers are the client versions the docs named on those dates. These details change often: re-check the live page before relying on one.

Contents:

- Claude Code
- Chat-app uploads and the Skills API
- Codex
- Cursor
- GitHub Copilot
- Choosing the canonical folder
- Collisions and the team prefix

## Claude Code

Locations:

- Personal: `~/.claude/skills/<name>/SKILL.md`. Project: `.claude/skills/<name>/SKILL.md`. Enterprise: `.claude/skills/` in the managed settings directory.
- Nested: `<subdir>/.claude/skills/` for sessions started in or below that subfolder; when a nested name clashes, it gets a path prefix such as `/apps/web:deploy`.
- `.claude/skills/` inside a directory passed with `--add-dir`.
- Plugins: `<plugin>/skills/<name>/SKILL.md`, invoked as `/plugin-name:skill-name`.
- Skills enabled on the user's claude.ai account sync into `~/.claude/skills/synced/` and take the `anthropic-skills:` prefix.
- Legacy command files in `.claude/commands/<name>.md` still work; a subfolder becomes `/dir:name`.
- The skills page lists no `.agents/skills` location, and the memory page says nothing under `.agents/` is read as instructions. Reach a skill kept in `.agents/skills` through a per-skill symlink in `.claude/skills`, then confirm it appears in the skill list.

Precedence and names:

- Same name: enterprise beats personal, personal beats project, and a skill beats a command file. Plugin skills are namespaced, so both load.
- The skill list still shows one entry when a personal copy shadows the project copy, and the docs name no command that reports which copy loaded (checked 2026-11-02). Before testing, look for the name in the personal folders ([testing.md](testing.md)).
- The client refuses names containing zero-width or control characters, private-use characters, characters that change text direction, unusual spaces, or `<` and `>`. Start with `--debug` and search the log for `[names]`.

Frontmatter and parsing:

- Keys it accepts: the six spec keys plus `when_to_use`, `argument-hint`, `arguments`, `disable-model-invocation`, `user-invocable`, `disallowed-tools`, `model`, `effort`, `context`, `agent`, `background`, `hooks`, `paths`, `shell`. Unknown keys are ignored silently.
- Malformed YAML loads the body with empty metadata: `/name` still works, automatic matching never does. `--debug` shows the parse error; `claude plugin validate .claude/skills` (v2.1.233 or later) finds frontmatter that does not parse.
- Angle brackets in a description display as `&lt;` and `&gt;`.

Invocation:

- `disable-model-invocation: true` removes the description from context and stops automatic use; `/name` still runs it. If the model calls the Skill tool for it anyway, Claude Code blocks the call and the agent suggests that the user run `/name` (checked 2026-11-06), so a command file that routes to such a skill cannot load it. `user-invocable: false` hides it from the menu and stops `/name` from running it, but the model can still invoke it.
- A `/name` typed at the start of a message runs the skill. Typed after other text, it does not run directly; it counts as permission the model may use while answering.
- `allowed-tools` pre-approves the listed tools for the turn that invokes the skill and clears on the next message. It restricts nothing, and workspace trust does not gate it: a project skill's `allowed-tools` applies even in a non-interactive run in a folder nobody trusted.
- `${CLAUDE_SKILL_DIR}` expands to the skill's folder in the body and in `allowed-tools` Bash rules, which allows the one safe pattern: pre-approving the skill's own script by path ([safety-and-permissions.md](safety-and-permissions.md)).
- Injected shell commands (an exclamation mark before a backtick span, or a fenced block opened with three backticks and an exclamation mark) run before the model sees the skill. A failing command aborts the invocation, except exit code 1 from search and comparison commands. A command matching a deny rule also aborts it. These blocks do nothing in chat apps or the API. `"disableSkillShellExecution": true`, best set in managed settings, replaces each one in user, project, plugin and added-directory skills with a placeholder (checked 2026-11-06).

Listing budget:

- Each entry's description plus `when_to_use` is capped at 1,536 characters (`skillListingMaxDescChars`).
- The whole listing gets 1% of the context window (`skillListingBudgetFraction`, or `SLASH_COMMAND_TOOL_CHAR_BUDGET` as a fixed character count). Names are always listed; over budget, descriptions are dropped starting with the least-invoked skills.
- `/doctor` estimates the listing cost; `/skill-doctor` (v2.1.252 or later) shows each skill's context cost and usage; the Skills row in `/context` shows the size after the budget; the debug log records an overflow.
- `skillOverrides` in settings sets a skill to `on`, `name-only`, `user-invocable-only` or `off`; the `/skills` menu stores the choice in `.claude/settings.local.json`. It does not apply to plugin skills.

Lifecycle:

- The rendered skill enters the conversation once and stays; the file is not re-read on later turns.
- After compaction, the latest invocation of each skill is re-attached, first 5,000 tokens each, within 25,000 tokens shared, most recent first.
- The client watches `~/.claude/skills/`, the project `.claude/skills/` and `--add-dir` skill folders, and loads changes mid-session. A new top-level skills folder needs `/reload-skills`.
- Cloud sessions and Cowork do not read `~/.claude/skills/`; they load the skills enabled on the claude.ai account. A cloud scheduled task that calls a local-only skill reports it as not found. Desktop scheduled tasks run locally and do load personal skills.
- `--bare` skips skill discovery and never gives the model the skill list (a folder passed with `--add-dir` still loads its skills); never run trigger tests in bare mode. The headless page says bare mode will become the default for `-p` in a future release (checked 2026-11-06).
- `AGENTS.md` is read only when no `CLAUDE.md` or `CLAUDE.local.md` exists in the working directory or above (v2.1.277 or later).

## Chat-app uploads and the Skills API

- Uploads to claude.ai, the Skills API and the `package_skill.py` packaging script accept only `name`, `description`, `license`, `compatibility`, `metadata` and `allowed-tools`. Any other key fails with "Unexpected key(s) in SKILL.md frontmatter".
- The name cannot contain the reserved words "anthropic" or "claude"; name and description cannot contain XML tags.
- API skills run with no network access and no runtime package installs; a request takes at most 20 skills.
- Custom skills uploaded to the chat app are private to the uploader by default; Team and Enterprise plans can share them with colleagues or publish them to the organisation's library (checked 2026-11-06). API skills are shared across the workspace.

## Codex

Locations and names:

- `.agents/skills` in every directory from the working directory up to the repository root; `$HOME/.agents/skills`; `/etc/codex/skills`; bundled system skills. Symlinked skill folders are followed.
- Two skills with one name are not merged; both appear in the selector.
- Frontmatter: `name` and `description` are required; no other keys are documented.

Invocation and budget:

- Explicit: `$skill-name`, or `/skills`, in the CLI and IDE extension. Implicit: the description matches the task.
- `agents/openai.yaml` inside the skill folder holds UI metadata, tool dependencies and the invocation policy. `policy.allow_implicit_invocation: false` makes the skill explicit-only; the default is true.
- Disable a skill with a `[[skills.config]]` entry in `~/.codex/config.toml` naming its `name` or the `path` of its SKILL.md, with `enabled = false`, then restart.
- The initial skills list uses at most 2% of the context window, or 8,000 characters when the window size is unknown. Descriptions are shortened first; with many skills some are omitted with a warning. `skills.max_context_tokens` sets a different budget, up to 10,000 tokens.
- Built-in `$skill-creator` creates skills and `$skill-installer` installs curated ones.
- The skills page does not say how to confirm a skill loaded during a session. The ChatGPT desktop app lists skills under Skills in its sidebar, and ChatGPT invokes one when you type `@` and pick it.

Other facts:

- Custom prompts in `~/.codex/prompts/` (invoked as `/prompts:name`) are deprecated in favour of skills and are not shared through the repository.
- OpenAI's skill-creator `quick_validate.py` accepts only `name`, `description`, `license`, `allowed-tools` and `metadata`, so it rejects `compatibility`, and it rejects angle brackets in descriptions.
- `AGENTS.md` files are combined up to `project_doc_max_bytes`, 32 KiB by default.
- Interactive read-only work: `codex --sandbox read-only --ask-for-approval on-request`; network access is off by default.
- Apps (connectors) are on by default (`features.apps`), and the sandbox does not control their traffic; installed plugins can bring their own MCP servers (`plugins.<plugin>.mcp_servers.<server>.enabled`). Checked 2026-11-06 on the configuration reference.
- Non-interactive runs: `codex exec` uses a read-only sandbox by default, needs a Git repository, streams JSON Lines events with `--json` and writes no session rollout files with `--ephemeral` (checked 2026-11-06). The stream defines no skill event.

## Cursor

Locations:

- Project: `.agents/skills/` and `.cursor/skills/`. User: `~/.agents/skills/` and `~/.cursor/skills/`. Compatibility: `.claude/skills/`, `.codex/skills/`, `~/.claude/skills/` and `~/.codex/skills/`.
- Cursor walks each skills root recursively and loads any SKILL.md it finds, including folders in nested project subdirectories. A template named SKILL.md under `assets/` becomes a skill.
- Duplicates, symlinks and a skill reachable from two roots are not addressed in the docs. Check the skill list after installing.

Frontmatter and invocation:

- Documented keys: `name` and `description` (required), `paths`, `disable-model-invocation`, `icon`, `color`, `metadata`; legacy `globs` is accepted.
- Type `/` in Agent chat and pick the skill to attach it to one message; use it as a Custom Mode to keep it for a session. With `disable-model-invocation: true` the skill is used only when typed.
- `/create-skill` scaffolds a skill. `/migrate-to-skills` converts eligible dynamic rules and user or workspace commands into skills; rules set to always apply, glob rules and user rules are not migrated. Check the converted frontmatter.
- See installed skills under Customize > Skills; skills from plugins or the project appear under Agent Decides.

Cloud and automations:

- User skills in `~/.cursor/skills/` reach Cloud Agents only with Sync Skills for Cloud Agents turned on (Settings > Agents). Synced skills are private to the user.
- Automations do not load synced personal skills, even when set to run as the user: put team skills in the repository's skills folder.
- `~/.agents/skills/` and unsynced local skills are not copied to Cloud Agents, remote SSH sessions or self-hosted workers.
- Rules live in `.cursor/rules/` as `.mdc` files; a plain `.md` file there is ignored by the rules system.

## GitHub Copilot

- Project skills: `.github/skills`, `.claude/skills` or `.agents/skills`. Personal: `~/.copilot/skills` or `~/.agents/skills`.

## Choosing the canonical folder

Keep one canonical copy of each team skill in the repository, then make every client in use see it once (the one recorded exception, a Cursor double listing, is below).

- One client only: that client's own project folder.
- Claude Code and Cursor: `.claude/skills/` (Cursor reads it for compatibility).
- Any mix that includes Codex: `.agents/skills/` is canonical (Codex, Cursor and Copilot read it), plus one symlink per skill in `.claude/skills/` for Claude Code.
- Cursor and Codex without Claude Code: `.agents/skills/`.
- Then open each client's skill list in a fresh clone and count the entries. The pass rule is one entry per client, with one exception. Cursor reads both `.agents/skills/` and `.claude/skills/`, so it may show the symlinked skill twice. That passes only when both entries resolve to the same folder, Cursor's trigger gate is met with both entries present, and the eval record and review checklist note the double listing. Never remove the `.claude/skills/` link to fix the count; Claude Code needs it.
- Windows clones without symlink support check a link out as a small text file and the skill disappears for that colleague. Include a Windows machine in the fresh-clone test if anyone on the team uses one.
- Make a plugin only when several projects need the same versioned set of skills; one repository is served by its own project folder.

## Collisions and the team prefix

- A stale personal copy beats the project copy in Claude Code, so a colleague can run last quarter's version without knowing, and Cursor also loads `~/.claude/skills/` and `~/.codex/skills/` in every project. Drafts belong in the drafts folder, never a personal skills folder; ask people to delete personal copies after a skill ships.
- Codex lists both copies of a duplicated name, which costs listing budget and splits triggering.
- Cursor's recursive discovery loads nested copies and stray templates.
- Prefix every team skill with a short team or company slug (`acme-pacing-review`), never use a vendor's or a pack skill's bare name, and never name a template or fixture SKILL.md (lint L12).
