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
| Type | For |
|---|---|
feat | New feature |
fix | Bug fix |
refactor | Code change that is not a fix or feature |
docs | Documentation only |
test | Adding 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
| Syntax | Matches |
|---|---|
$VAR | Single AST node |
$$$ARGS | Zero 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 . 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:
| Method | Time | Cost | Turns | Success |
|---|---|---|---|---|
| Dev Browser | 3m 53s | $0.88 | 29 | 100% |
| Playwright MCP | 4m 31s | $1.45 | 51 | 100% |
| Playwright Skill | 8m 07s | $1.45 | 38 | 67% |
| Claude Chrome Extension | 12m 54s | $2.81 | 80 | 100% |
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.