skills/writing-skills/reference/best-practices.md · view on GitHub (opens in a new tab)
Detail behind the SKILL.md workflow. Read the section you need.
Your skill shares context with the system prompt, conversation history, other skills’ metadata, and the user’s actual request. Only name/description are pre-loaded; the body loads on invocation — but once loaded it stays for the session, so every line is a recurring cost.
Default assumption: Claude is already very smart. Add only what it lacks. Challenge each piece: “Does Claude need this? Can I assume it knows? Does this paragraph justify its tokens?”
Concise (~50 tokens):
## Extract PDF text
Use pdfplumber:
```python
import pdfplumber
with pdfplumber.open("file.pdf") as pdf:
text = pdf.pages[0].extract_text()
```Too verbose (~150 tokens): a paragraph explaining what PDFs are, that libraries exist, that pdfplumber is one option, how to pip install it… all of which Claude already knows.
The description is the single most important field — Claude picks among potentially 100+ skills using it alone.
Good:
description: Analyze Excel spreadsheets, create pivot tables, generate charts. Use when analyzing Excel files, spreadsheets, tabular data, or .xlsx files.
description: Generate descriptive commit messages by analyzing git diffs. Use when the user asks for help writing commit messages or reviewing staged changes.Bad: Helps with documents · Processes data · Does stuff with files
Think of Claude as a robot on a path.
python scripts/migrate.py --verify --backup. Do not modify the command or add flags.”Over-constraining an open task wastes tokens and judgment; under-constraining a fragile one causes errors.
SKILL.md is a table of contents that points to detail loaded on demand.
Pattern 1 — High-level guide with references. Quick-start inline; “For form filling, see FORMS.md; for the API, see REFERENCE.md.”
Pattern 2 — Domain organization. Split by domain so unrelated domains cost nothing:
bigquery-skill/
├── SKILL.md # overview + navigation
└── reference/
├── finance.md
├── sales.md
└── product.mdA grep -i "revenue" reference/finance.md hint helps Claude jump straight to the right place.
Pattern 3 — Conditional detail. Show the common path inline; link advanced/edge cases (“For tracked changes, see REDLINING.md”).
Keep references one level deep. SKILL.md → file.md is fine; SKILL.md → a.md → b.md is not — Claude may head deeply-nested files and read them incompletely. Add a table of contents to any reference file over ~100 lines so partial reads still reveal full scope.
For complex multi-step work, give an explicit checklist Claude can copy into its response and tick off:
Task Progress:
- [ ] Step 1: Analyze the form (run analyze_form.py)
- [ ] Step 2: Create field mapping (edit fields.json)
- [ ] Step 3: Validate (run validate_fields.py)
- [ ] Step 4: Fill (run fill_form.py)
- [ ] Step 5: Verify (run verify_output.py)Clear numbered steps stop Claude skipping validation.
Feedback loop: run validator → fix → repeat, and “only proceed when validation passes.” Works with scripts (validate.py) or with a reference doc as the “validator” (compare against STYLE_GUIDE.md). For batch/destructive/high-stakes work, use plan → validate → execute: have Claude write a structured plan file, validate it with a script (verbose, specific errors), then apply.
Pre-written scripts beat regenerated code: more reliable, no code in context, consistent, faster.
FileNotFoundError/PermissionError etc. inside the script rather than letting it throw for Claude to untangle.REQUEST_TIMEOUT = 30 # slow connections), not TIMEOUT = 47.analyze_form.py to extract fields” (execute) vs “See analyze_form.py for the algorithm” (read).scripts/helper.py), never backslashes — Unix paths work everywhere.ServerName:tool_name (e.g. GitHub:create_issue), else “tool not found”.${CLAUDE_SKILL_DIR} for bundled script paths so they resolve at personal/project/plugin install locations.For the specific case of wrapping an API with no CLI (a bundled script with abstracted subcommands plus a generic passthrough), see api-wrappers.md.
<details> “Old patterns (deprecated)” block.@imports in SKILL.md — they don’t work; link in prose.Build evaluations before extensive docs, so you solve real gaps:
Develop with two roles: Claude A helps you write/refine the skill; a fresh Claude B uses it on real tasks; you observe B’s behavior and bring specifics back to A (“B forgot to filter test accounts even though the skill mentions it — make that rule more prominent”). Watch for: unexpected file-read order (structure unclear), missed references (links not prominent), a file never read (unnecessary or poorly signaled), repeated reads of one file (maybe promote it into SKILL.md). Iterate on observed behavior, not assumptions.
Core quality
Code & scripts
Testing
/name and automatic triggering; team feedback folded in if shared.