CLAUDE.md gives the agent its rules and workflow. But rules without depth only get you so far. "Use the Page Object Model" is a rule, but how exactly do you structure a page object? What's the difference between a locator getter and an action method? How do you compose components into page objects?
This is where skill files come in.
🤔 What Is a Skill File?
A skill file is a detailed, focused markdown document that covers one area of your testing framework in depth. Where CLAUDE.md tells the agent what to do, skills tell the agent how to do it.
The scaffold comes with 13 skills, all living in .claude/skills/:
.claude/skills/
├── selectors/SKILL.md → Locator priority, forbidden patterns, examples
├── page-objects/SKILL.md → POM structure, getters vs actions, registration
├── fixtures/SKILL.md → DI pattern, fixture creation, merging
├── test-standards/SKILL.md → Test structure, imports, tagging, steps
├── api-testing/SKILL.md → apiRequest fixture, schema validation
├── data-strategy/SKILL.md → Factories vs static JSON, Faker usage
├── type-safety/SKILL.md → Zod schemas, TypeScript strict mode
├── enums/SKILL.md → Enum conventions and naming
├── config/SKILL.md → Config patterns, environment variables
├── helpers/SKILL.md → Helper functions, auth helpers
├── browser-use/SKILL.md → Live app exploration with browser automation
├── common-tasks/SKILL.md → Prompt templates, verification checklist
└── refactor-values/SKILL.md → Safe refactoring of enums and static data
Each one is loaded on demand, not all at once. The agent reads only the skill that's relevant to what it's currently doing.
🧠 Why Not Put Everything in CLAUDE.md?
A single giant instruction file has a real problem. The further down the page a rule lives, the less likely the AI is to apply it consistently. Context windows have limits, and even when they don't, a 5,000 word instruction file is harder to reason about than a 300 word one.
Skills solve this with lazy loading. The agent reads the orchestrator (CLAUDE.md) first. Short, high-level, fast. When it needs to work on a specific area, it reads the relevant skill. Deep expertise, loaded exactly when needed.
Agent working on a page object:
→ CLAUDE.md: "Read selectors and page-objects skills for pages/**"
→ Loads selectors/SKILL.md
→ Loads page-objects/SKILL.md
→ Now has full expertise for this specific task
→ Generates code confidently and correctly
📖 What's Inside a Skill File?
Let's look at what the selectors skill actually contains:
The priority rule with reasoning:
Priority order:
1. getByRole() - Tests behaviour, survives CSS/ID changes
2. getByLabel() - Tied to accessible form labels
3. getByPlaceholder() - Tied to input hint text
4. getByText() - Matches visible text content
5. getByTestId() - Last resort, when no semantic option exists
Forbidden: XPath, CSS class selectors (.btn-primary)
Examples of correct vs incorrect usage:
// ✅ Correct
page.getByRole("button", { name: "Submit Order" });
page.getByLabel("Email address");
// ❌ Wrong: fragile, will break on CSS changes
page.locator(".submit-btn");
page.locator("#email-input");
page.locator('xpath=//button[@class="btn"]');
Edge cases:
- Buttons with icons only: use getByRole('button', { name: /icon label/i })
- Dynamic text: use getByRole with partial name match
- Inside a shadow DOM: note the limitation, escalate to human review
A skill file is essentially what you'd tell a new team member on their first code review. "We do it this way, here's why, here are the gotchas".
🔗 The common-tasks Skill
One skill deserves special attention: common-tasks. It contains prompt templates, pre-written instructions for the most frequent tasks an agent performs:
## Create a Page Object
Before starting:
1. Read selectors/SKILL.md and page-objects/SKILL.md
2. Navigate to the page using browser-use
3. Discover: button names, label text, heading roles
Generate:
- pages/{area}/{name}.page.ts
- Register in fixtures/pom/page-object-fixture.ts
Verification checklist:
- [ ] No XPath
- [ ] No hardcoded strings in test files
- [ ] No `any` type
- [ ] Linting passes
- [ ] Tests run and pass
This is the agent's playbook. Instead of reasoning from scratch about how to create a page object, it has a structured checklist to follow. The output is consistent because the process is consistent.
📝 Writing Your Own Skill Files
The skills that ship with the scaffold are a starting point. As your project grows, you'll discover new conventions that need documenting, and new anti-patterns that need blocking.
A good skill file has four parts:
- The rule: What the agent should do (or not do) in this area
- The reasoning: Why the rule exists (helps the agent generalize)
- Code examples: Correct and incorrect, clearly labeled
- Edge cases: The situations where the rule gets tricky
Keep them short. A skill file that is short and concise will get used. One that is long and verbose won't.
🔄 Skills as a Team Knowledge Base
Here's something that's easy to miss. Skill files aren't just for AI. They're documentation of your team's decisions.
When a new colleague joins your team, they can read the skill files to understand why things are done the way they are. When you make a decision in a code review ("we always use z.strictObject() because here's what happened that one time"), you add it to the relevant skill file. The AI and the humans stay aligned.
Over time, the .claude/skills/ folder becomes a living record of your team's accumulated QA knowledge.
🙏🏻 Thank you for reading! Skills are what separate a consistent AI-generated codebase from a chaotic one. But rules and skills only get the agent so far. It also needs to see the actual application before writing code for it. That's the subject of the next article.
You can find the Public README.md file for the scaffold on GitHub: Playwright Scaffold
You can get access to the private GitHub repository here: Get Access




Top comments (0)