/ src / app / api / claude-skills / route.ts
route.ts
 1  import { NextResponse } from 'next/server'
 2  import fs from 'fs'
 3  import path from 'path'
 4  import os from 'os'
 5  export const dynamic = 'force-dynamic'
 6  
 7  
 8  /** GET /api/claude-skills — discover skills from ~/.claude/skills/ */
 9  export async function GET(_req: Request) {
10    const skillsDir = path.join(os.homedir(), '.claude', 'skills')
11    const skills: { id: string; name: string; description: string }[] = []
12  
13    if (!fs.existsSync(skillsDir)) {
14      return NextResponse.json(skills)
15    }
16  
17    const entries = fs.readdirSync(skillsDir, { withFileTypes: true })
18    for (const entry of entries) {
19      if (!entry.isDirectory()) continue
20      const skillMd = path.join(skillsDir, entry.name, 'SKILL.md')
21      if (!fs.existsSync(skillMd)) continue
22  
23      try {
24        const content = fs.readFileSync(skillMd, 'utf8')
25        // Parse YAML frontmatter between --- markers
26        const match = content.match(/^---\n([\s\S]*?)\n---/)
27        if (!match) continue
28  
29        const frontmatter = match[1]
30        const nameMatch = frontmatter.match(/^name:\s*(.+)$/m)
31        const descMatch = frontmatter.match(/^description:\s*(.+)$/m)
32  
33        skills.push({
34          id: entry.name,
35          name: nameMatch?.[1]?.trim() || entry.name,
36          description: descMatch?.[1]?.trim() || '',
37        })
38      } catch {
39        // Skip malformed skill files
40      }
41    }
42  
43    return NextResponse.json(skills)
44  }