Where each product keeps them
claude.ai takes custom skills as zip files under Settings > Features, on Pro, Max, Team and Enterprise plans with code execution enabled, and each upload stays with one user. The API takes them through the /v1/skills endpoints, runs them with the code execution tool and shares them across the workspace. Claude Code needs no upload: it reads ~/.claude/skills/ and the project's .claude/skills/.
The sandbox is different too
On the API a skill runs in a container with no network access, using only the packages already installed. On claude.ai that access can be full, partial or absent, depending on user and admin settings. In Claude Code it matches any other program on the computer. So a skill that calls an outside service can work in Claude Code and fail on the API; say so in its compatibility field.
Frontmatter that survives an upload
Claude Code accepts fields the specification does not define, such as disable-model-invocation. Uploads to claude.ai and the Skills API, and packaging with package_skill.py from anthropics/skills, accept only the six specification fields: name, description, license, compatibility, metadata and allowed-tools. Anything else fails with an error rather than being ignored. Anthropic's platform documentation also rules out XML tags and the words "anthropic" and "claude" in name.