Authoring Skills for the Claude App & Cowork
The skill format is identical everywhere. What differs in the app/Cowork/sandbox is the runtime and
how skills load. This covers only those differences — the craft lives in
writing-skills. For local Claude Code config instead, see
claude-md-and-folder-standards.
How skills load here (the gotcha)
- Cowork and cloud sessions do NOT read your local
~/.claude. They load skills enabled on yourclaude.aiaccount (synced from the desktop app's Customize config) plus skills committed to the repo's.claude/skills/. A skill that only lives on your machine won't reach them — enable it on the account or commit it to the repo. - There is no
CLAUDE.md,settings.json, or hooks layer to lean on. The skill must carry its own context; don't reference machine-local config that won't exist in the session.
The sandbox is real — use it
Skills here run in a code-execution environment with a filesystem, bash, and code execution.
- Bundle scripts instead of asking the model to regenerate code. A committed
scripts/foo.pyis more reliable, consistent, and cheaper (only its output enters context) than generated code. Tell the model whether to run it or read it as reference. - Solve in the script; don't defer to the model. Handle the missing file, the bad input — return a sane default with a clear message rather than throwing for the model to untangle.
- No voodoo constants. Justify every timeout/retry in a comment; if you can't, neither can the model.
- Bundled reference files cost nothing until read — ship complete API docs, datasets, examples, and let progressive disclosure pull them in on demand.
Dependencies differ by surface
- claude.ai / desktop app: can install from npm and PyPI at runtime — list required packages in the skill so they get installed.
- Claude API: no network, no runtime install — assume nothing beyond the base image.
- Never assume a package is present; state the install step.
Prove it works
- Write evals before prose. Run the task without the skill, capture where it fails, and build a few concrete scenarios that pin those gaps. The skill's job is to pass them — nothing more.
- Author with one model, test with a fresh one. Iterate the skill in one session; verify it in a clean session that only has the skill loaded. Fix what the fresh session actually gets wrong.
- Test on every model tier you'll ship to — Haiku may need detail Opus would find redundant.
Portable hygiene
- Forward-slash paths only (
scripts/x.py), never backslashes. - Fully-qualify MCP tools as
ServerName:tool_name, or the model may not find them.