back to docs
ai

Claude Code Skills

Reusable custom skills for extending Claude Code

Skills are installable prompt files that extend Claude Code as slash commands. Drop a SKILL.md into ~/.claude/skills/<skill-name>/ and it becomes available as /<skill-name> automatically.

1. Installing a skill

mkdir -p ~/.claude/skills/my-skill
# place your SKILL.md inside

The SKILL.md format:

---
name: my-skill
description: When and why Claude should use this skill
---

# My Skill

Instructions for Claude go here...

Here are the skills I use regularly.


2. commit-message

Generates commit messages following Conventional Commits. I invoke it with /commit-message or Claude picks it up automatically when committing.

Format: type(scope): description

TypeFor
featNew feature
fixBug fix
refactorCode change that is not a fix or feature
docsDocumentation only
testAdding or updating tests

Example:

feat(auth): add password reset flow

Keep descriptions under 50 characters. Add a blank line and a body when more context is needed.


3. ast-grep

Structural code search and replacement that matches syntax, not raw text. This skill makes Claude prefer ast-grep over grep for anything involving code patterns.

Good for debugging, refactoring, API migrations, and finding specific hook or component usage.

a. Basic usage

# Search
ast-grep --pattern 'useState($$$)' --lang tsx src/

# Preview changes
ast-grep --pattern 'console.log($$$)' --rewrite '' --lang typescript .

# Apply changes
ast-grep --pattern 'console.log($$$)' --rewrite '' --lang typescript . --update-all

b. Meta-variables

SyntaxMatches
$VARSingle AST node
$$$ARGSZero or more nodes

c. Common patterns

# useEffect without a deps array
ast-grep --pattern 'useEffect(() => { $$$ })' --lang tsx .

# All fetch calls
ast-grep --pattern 'fetch($$$)' --lang typescript .

# 'use client' directives
ast-grep --pattern "'use client'" --lang typescript .
Always preview before applying

Run without --update-all first to confirm the matches look right, then add the flag.


4. dev-browser

Browser automation with persistent page state using Playwright. Pages stay alive between scripts, including cookies and localStorage. Built by Sawyer Hood.

I use this for navigating sites, filling forms, taking screenshots, scraping, and testing UIs directly.

a. Why it beats the alternatives

The main thing that makes dev-browser stand out is the stateful server. Playwright MCP does an observe-think-act loop with individual tool calls, which is simple but slow. A plain Playwright skill runs full scripts end-to-end, which is fast but fragile because each run starts fresh. Dev-browser sits in between. A persistent server holds all page state, and Claude writes small focused scripts that connect to it.

The numbers from the official benchmark:

MethodTimeCostTurnsSuccess
Dev Browser3m 53s$0.8829100%
Playwright MCP4m 31s$1.4551100%
Playwright Skill8m 07s$1.453867%
Claude Chrome Extension12m 54s$2.8180100%

Faster, cheaper, and more reliable than the alternatives.

b. Setup

./skills/dev-browser/server.sh &

Wait for the Ready message, then run scripts:

cd skills/dev-browser && bun x tsx <<'EOF'
import { connect, waitForPageLoad } from "@/client.js";

const client = await connect("http://localhost:9222");
const page = await client.page("main");

await page.goto("https://example.com");
await waitForPageLoad(page);

console.log({ url: page.url(), title: await page.title() });

await client.disconnect();
EOF

c. Discovering elements

When you do not know the page layout, use getAISnapshot() to get a semantic ARIA tree in YAML:

const snapshot = await client.getAISnapshot("main");
// Shows roles, names, and [ref=eN] handles for each element

const element = await client.selectSnapshotRef("main", "e5");
await element.click();

A few rules:

  • One script, one action
  • Always await client.disconnect() at the end so the process exits cleanly
  • Inside page.evaluate(), use plain JavaScript only, no TypeScript syntax

5. windows-filepath

Prevents Claude from using forward slashes in file paths on Windows. Without this, Edit and Write operations fail silently because the path is not recognized.

When it kicks in: any file operation on Windows using Edit, Write, or MultiEdit.

# Wrong, will fail
D:/repos/project/file.tsx

# Correct
D:\\repos\\project\\file.tsx

The skill reminds Claude to stick with \\ consistently and never mix the two separator styles in the same path.

Command Palette
Search for a command to run...