Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Skills

Skills are domain-specific capabilities that can be added to agents to extend their functionality with specialized knowledge. Think of skills as "plugins" that give agents superpowers in specific domains.

What Are Skills?

While agents define roles and responsibilities, skills define capabilities and knowledge.

Analogy: Agents vs. Skills

Agent = Role (e.g., "Backend Developer")
  → Knows: Architecture patterns, clean code principles
  → Responsible for: Services, repositories, APIs
 
Skill = Capability (e.g., "Prisma ORM")
  → Knows: Prisma schema syntax, migration commands
  → Provides: Database modeling patterns, query patterns
 
Backend Agent + Prisma Skill
  → Can do: Design schemas, write migrations, optimize queries

Skill Definition

Skills are defined in .claude/skills/ as markdown files:

---
name: prisma-orm
applies_to: [backend, architect]
description: Prisma ORM expertise for database modeling and queries
---
 
# Prisma ORM Skill
 
You have expertise in Prisma ORM.
 
## Schema Design
 
```prisma
model User {
  id        String   @id @default(cuid())
  email     String   @unique
  password  String
  posts     Post[]
}

Common Patterns

Relations

// One-to-many
model User {
  posts Post[]
}
 
model Post {
  author   User @relation(fields: [authorId], references: [id])
  authorId String
}

Migrations

npx prisma migrate dev --name init
npx prisma migrate deploy

Best Practices

  • Always use @default(cuid()) for IDs
  • Use @unique for email fields
  • Add indexes for frequently queried fields
 
## Why Skills Exist
 
### Problem: Agents Are Generalists
 
Base agents have **broad knowledge** but **shallow domain-specific expertise**:

Backend Agent: ✅ Knows clean architecture ✅ Knows REST API patterns ✅ Knows service/repository pattern ❌ Doesn't know Prisma-specific patterns ❌ Doesn't know Next.js 14 specific API routes ❌ Doesn't know Tailwind utility patterns

 
### Solution: Skills Add Specialization
 
Skills inject **deep domain knowledge** into agents:

Backend Agent + Prisma Skill: ✅ Knows clean architecture ✅ Knows REST API patterns ✅ Knows Prisma schema syntax ✅ Knows Prisma query patterns ✅ Knows migration workflow ✅ Knows relation modeling

 
## Skill Types
 
### 1. Technology Skills
 
Specific technologies and frameworks:
 
```markdown
---
name: nextjs-14
applies_to: [frontend, backend, architect]
description: Next.js 14 App Router expertise
---
 
# Next.js 14 Skill
 
## App Router Patterns
 
### Server Components (Default)
```tsx
// src/app/dashboard/page.tsx
async function getData() {
  const res = await fetch('https://api.example.com/data', {
    cache: 'no-store',
  });
  return res.json();
}
 
export default async function DashboardPage() {
  const data = await getData();
  return <div>{data.title}</div>;
}

Client Components (When Needed)

'use client';
 
export function InteractiveButton() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

Route Handlers

// src/app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';
 
export async function GET(req: NextRequest) {
  const users = await db.user.findMany();
  return NextResponse.json(users);
}
 
### 2. Database Skills
 
ORM and database expertise:
 
```markdown
---
name: postgresql
applies_to: [backend, architect]
description: PostgreSQL database expertise
---
 
# PostgreSQL Skill
 
## Query Patterns
 
### Indexes
```sql
CREATE INDEX idx_user_email ON users(email);
CREATE INDEX idx_post_author ON posts(author_id);

Full-Text Search

SELECT * FROM posts
WHERE to_tsvector(title || ' ' || content) @@ to_tsquery('react');

Best Practices

  • Use TEXT instead of VARCHAR (no performance penalty)
  • Use TIMESTAMPTZ for timestamps (with timezone)
  • Add foreign keys for data integrity
  • Use EXPLAIN ANALYZE to optimize queries
 
### 3. Styling Skills
 
CSS and styling frameworks:
 
```markdown
---
name: tailwind-css
applies_to: [frontend]
description: Tailwind CSS utility-first styling
---
 
# Tailwind CSS Skill
 
## Utility Patterns
 
### Responsive Design
```tsx
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  {items.map(item => <Card key={item.id} {...item} />)}
</div>

Dark Mode

<div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
  <h1>Adaptive to theme</h1>
</div>

Component Patterns

Card Component

export function Card({ children, className }) {
  return (
    <div className={cn(
      "bg-white rounded-lg shadow-md p-6",
      "dark:bg-gray-800",
      className
    )}>
      {children}
    </div>
  );
}
 
### 4. Testing Skills
 
Testing frameworks and strategies:
 
```markdown
---
name: vitest
applies_to: [tester]
description: Vitest testing framework expertise
---
 
# Vitest Skill
 
## Test Patterns
 
### Unit Tests
```typescript
import { describe, it, expect, vi } from 'vitest';
 
describe('UserService', () => {
  it('should create user with hashed password', async () => {
    const user = await service.register({
      email: 'test@example.com',
      password: 'password123'
    });
    expect(user.password).not.toBe('password123');
    expect(user.password).toMatch(/^\$2[ayb]\$.{56}$/);
  });
});

Mocking

const mockRepo = {
  findByEmail: vi.fn().mockResolvedValue(null),
  create: vi.fn().mockResolvedValue({ id: '1' })
};

Coverage Configuration

// vitest.config.ts
export default defineConfig({
  test: {
    coverage: {
      provider: 'v8',
      reporter: ['text', 'json', 'html'],
      thresholds: {
        lines: 80,
        functions: 80,
        branches: 80,
        statements: 80
      }
    }
  }
});
 
### 5. Domain Skills
 
Industry-specific knowledge:
 
```markdown
---
name: ecommerce
applies_to: [backend, frontend, architect]
description: E-commerce domain expertise
---
 
# E-commerce Domain Skill
 
## Common Patterns
 
### Shopping Cart
```typescript
interface CartItem {
  productId: string;
  quantity: number;
  variant?: string;
}
 
interface Cart {
  items: CartItem[];
  subtotal: number;
  tax: number;
  total: number;
}

Inventory Management

async function checkInventory(productId: string, quantity: number) {
  const product = await db.product.findUnique({ where: { id: productId } });
  if (product.stock < quantity) {
    throw new InsufficientStockError(product.stock, quantity);
  }
  return product;
}

Best Practices

  • Always use transactions for order creation
  • Implement optimistic locking for inventory
  • Cache product data but invalidate on updates
  • Use webhooks for payment status updates
 
## How Skills Work
 
### Skill Loading
 
When an agent is invoked, agentful:
 
1. **Detects applicable skills**
   ```bash
   # Reads skill frontmatter
   applies_to: [backend, architect]
 
   # Checks current agent
   current_agent = "backend"
   # → Load this skill
  1. Injects skill knowledge
    • Agent definition + skill content = enhanced capabilities
    • Agent can now use skill-specific patterns
    • Agent knows best practices from skill
  2. Applies to implementation
    • Backend agent using Prisma skill:
      // Knows to use Prisma patterns
      export class UserRepository {
        async findById(id: string) {
          return db.user.findUnique({ where: { id } });
        }
      }

Skill Composition

Multiple skills can be combined:

Backend Agent
  + Prisma Skill (database)
  + JWT Skill (authentication)
  + Zod Skill (validation)
  → Can build complete auth system

Creating Custom Skills

You can add your own skills in .claude/skills/:

---
name: your-skill-name
applies_to: [agent1, agent2]
description: What this skill provides
---
 
# Skill Name
 
Brief description of what this skill does.
 
## Patterns
 
### Pattern Name
```language
// Code example

Best Practices

  • Best practice 1
  • Best practice 2
 
### Example: Custom API Skill
 
```markdown
---
name: stripe-api
applies_to: [backend]
description: Stripe payment integration expertise
---
 
# Stripe API Skill
 
## Payment Patterns
 
### Create Payment Intent
```typescript
import Stripe from 'stripe';
 
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
 
async function createPaymentIntent(amount: number, currency: string) {
  const paymentIntent = await stripe.paymentIntents.create({
    amount: amount * 100, // Convert to cents
    currency,
    automatic_payment_methods: { enabled: true },
  });
  return paymentIntent;
}

Webhook Handler

import { headers } from 'next/headers';
 
export async function POST(req: Request) {
  const body = await req.text();
  const sig = headers().get('stripe-signature')!;
 
  let event: Stripe.Event;
  try {
    event = stripe.webhooks.constructEvent(
      body,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET!
    );
  } catch (err) {
    return NextResponse.json({ error: 'Invalid signature' }, { status: 400 });
  }
 
  switch (event.type) {
    case 'payment_intent.succeeded':
      // Handle successful payment
      break;
  }
 
  return NextResponse.json({ received: true });
}

Best Practices

  • Always verify webhook signatures
  • Store payment intent IDs in your database
  • Handle idempotency keys for retries
  • Use Stripe CLI for local testing
 
## Skill Discovery
 
### Automatic Skill Loading
 
agentful automatically discovers and loads skills:

.claude/ ├── agents/ │ ├── backend.md │ └── frontend.md └── skills/ ├── prisma-orm.md (applies_to: [backend]) ├── nextjs-14.md (applies_to: [frontend, backend]) ├── tailwind-css.md (applies_to: [frontend]) └── vitest.md (applies_to: [tester])

When @backend agent invoked: → Loads: prisma-orm.md → Loads: nextjs-14.md (if applicable) → Combines with backend.md

 
### Skill Priority
 
When skills conflict, **most specific wins**:
 
```javascript
Generic skill: "database" (applies_to: [backend])
Specific skill: "prisma-orm" (applies_to: [backend])
 
→ Use prisma-orm (more specific)

Skills vs. Agent Specialization

When to Use Skills

Use skills when:

  • Multiple agents need the same capability
    • Example: Both backend and architect need PostgreSQL knowledge
  • Capability is optional or tech-specific
    • Example: Not all backend agents use Prisma
  • Capability can be composed
    • Example: Backend + Prisma + JWT = complete auth system

When to Use Agents

Use agents when:

  • Role is fundamentally different
    • Example: Backend vs. Frontend (different domains)
  • Responsibilities don't overlap
    • Example: Tester never reviews code
  • Scope needs strict boundaries
    • Example: Backend never touches UI

Skill Examples

Example 1: Adding React Query Skill

---
name: react-query
applies_to: [frontend]
description: React Query for server state management
---
 
# React Query Skill
 
## Query Patterns
 
### Fetching Data
```tsx
import { useQuery } from '@tanstack/react-query';
 
function UserProfile({ userId }) {
  const { data: user, isLoading, error } = useQuery({
    queryKey: ['user', userId],
    queryFn: () => fetch(`/api/users/${userId}`).then(r => r.json()),
  });
 
  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error loading user</div>;
 
  return <div>{user.name}</div>;
}

Mutations

import { useMutation, useQueryClient } from '@tanstack/react-query';
 
function UpdateProfile() {
  const queryClient = useQueryClient();
 
  const mutation = useMutation({
    mutationFn: (data) => fetch('/api/users', {
      method: 'PUT',
      body: JSON.stringify(data),
    }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['user'] });
    },
  });
}
 
### Example 2: Adding Docker Skill
 
```markdown
---
name: docker
applies_to: [backend, architect]
description: Docker containerization expertise
---
 
# Docker Skill
 
## Dockerfile Patterns
 
### Node.js App
```dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
 
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["npm", "start"]

Docker Compose

version: '3.8'
services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://db:5432/myapp
    depends_on:
      - db
 
  db:
    image: postgres:16
    volumes:
      - postgres_data:/var/lib/postgresql/data
 
volumes:
  postgres_data:
 
## Best Practices for Skills
 
### DO ✅
 
- **Keep skills focused** - One capability per skill
- **Provide examples** - Show common patterns
- **Specify applies_to** - Clear which agents use it
- **Document best practices** - Share domain knowledge
- **Keep updated** - Match current framework versions
 
### DON'T ❌
 
- **Don't duplicate agent logic** - Skills add, don't replace
- **Don't make skills too broad** - "web-development" is too broad, "nextjs-14" is good
- **Don't assume tech stack** - Make skills optional
- **Don't hardcode paths** - Use generic patterns
 
## Summary
 
Skills are agentful's extensibility mechanism:
 
- **Domain-specific** - Deep knowledge in specific areas
- **Composable** - Combine multiple skills
- **Optional** - Load only what's needed
- **Extensible** - Add your own skills
- **Specialized** - Give agents superpowers
 
They transform generalist agents into **specialized experts** while keeping the agent system simple and maintainable.
 
**Next:** [Learn about state management](./state-management)