Universal pattern detector - learns from ANY codebase through sample analysis
Analyze ANY codebase to learn existing API patterns. Works with any framework, structure, or convention.
When this skill is invoked, Claude MUST perform these steps in order:
Read tool to read package.json in project rootdependenciesdevDependenciesFrom package.json, identify:
| Category | Check for | Result |
|---|---|---|
| Framework | react, vue, @angular/core, svelte |
Set framework |
| HTTP Client | axios, ky, got |
Set httpClient |
| Data Fetching | @tanstack/react-query, swr, @reduxjs/toolkit |
Set dataFetching |
| Language | typescript in devDeps |
Set language to typescript or javascript |
Report findings:
📦 package.json analysis:
Framework: <framework> + <language>
HTTP Client: <httpClient or "fetch (native)">
Data Fetching: <dataFetching or "none detected">
Use Glob tool with these patterns in order:
1. src/**/api/**/*.{ts,js,tsx,jsx}
2. src/**/services/**/*.{ts,js}
3. src/**/hooks/**/*{api,query,fetch}*.{ts,js}
4. lib/api/**/*.{ts,js}
5. api/**/*.{ts,js}
If NO files found:
🔍 No existing API code foundIf files found:
🔍 Found <count> potential API filesFor each discovered file (max 5 files):
Use Read tool to read file content
Extract patterns:
Record findings in structured format:
File: <path>
- Imports: <pattern>
- Exports: <pattern>
- Functions: <pattern>
- HTTP: <pattern>
- Types: <pattern>
📂 Detected patterns:
Structure: <pattern> (confidence: <X>%)
HTTP Client: <pattern>
Data Fetching: <pattern>
Types: <pattern>
Naming: <pattern>
📁 Sample files:
API: <best sample path>
Types: <best sample path>
Hooks: <best sample path>
If Step 3 found no files OR Step 5 confidence < 50%:
If user provides no sample:
For full error code reference, see ../../docs/ERROR-CODES.md.
Error: "[E501] ❌ Cannot find package.json"
Cause: Not in project root or no package.json exists
Fix: Run from project root directory
Action: Abort operation
Error: "[E501] ❌ Configuration file not found: .openapi-sync.json"
Cause: Project not initialized
Fix: Run /oas:init to initialize
Action: Abort operation
Warning: "[E402] ⚠️ No API files found in standard locations"
Cause: Project uses non-standard structure
Fix: Specify sample file manually
Recovery: Proceed to Interactive Fallback
Warning: "[E302] ⚠️ Could not read <filepath>, skipping..."
Cause: Permission denied or file corrupted
Recovery: Continue with other files
Warning: "[E402] ⚠️ Sample file doesn't contain extractable patterns"
Cause: File is empty, too simple, or uses unusual syntax
Fix: Provide a more representative sample
Recovery: Uses default patterns
Warning: "⚠️ Inconsistent patterns detected across files"
Detail: "Found: camelCase (60%), snake_case (40%)"
Recovery: Use majority pattern, report inconsistency
FSD (Feature-Sliced Design):
src/entities/{domain}/api/{domain}-api.ts
src/entities/{domain}/model/types.ts
src/features/{feature}/api/
Feature-based:
src/features/{feature}/api.ts
src/features/{feature}/hooks.ts
Flat:
src/api/{domain}.ts
src/hooks/use{Domain}.ts
Service-based:
src/services/{domain}.service.ts
src/services/{domain}Service.ts
| Package | Import Pattern | Usage Pattern |
|---|---|---|
| axios | import axios or import { } from 'axios' |
axios.get(), axios.create() |
| ky | import ky from 'ky' |
ky.get(), ky.post() |
| fetch | (native) | fetch(url) |
| custom | import { api } from '@/shared/api' |
api.get(), createApi() |
| Package | Import Pattern | Usage Pattern |
|---|---|---|
| React Query | from '@tanstack/react-query' |
useQuery(), useMutation() |
| SWR | import useSWR |
useSWR(key, fetcher) |
| RTK Query | createApi from toolkit |
api.endpoints.getX.useQuery() |
| Pattern | Example | Identification |
|---|---|---|
| Interface | interface User { } |
Uses interface keyword |
| Type alias | type User = { } |
Uses type keyword |
| Request suffix | GetUserRequest |
Type name ends with Request |
| Response suffix | GetUserResponse |
Type name ends with Response |
| DTO suffix | UserDTO, UserDto |
Type name ends with DTO/Dto |
Return this structure to the calling command:
{
"meta": {
"detectionMethod": "sample-analysis",
"confidence": 0.85,
"samplesAnalyzed": 5,
"framework": "react"
},
"structure": {
"type": "fsd",
"pattern": "src/entities/{domain}/api/{domain}-api.ts",
"discovered": ["src/entities/user/api/user-api.ts"]
},
"httpClient": {
"type": "custom-wrapper",
"import": "import { createApi } from '@/shared/api'",
"usage": "createApi().{method}<{Type}>(path)"
},
"dataFetching": {
"library": "react-query",
"version": "5",
"keyPattern": "factory"
},
"types": {
"location": "src/entities/{domain}/model/types.ts",
"style": "interface",
"naming": {
"request": "{Operation}Request",
"response": "{Entity}",
"entity": "{Entity}"
}
},
"samples": {
"api": { "path": "...", "content": "..." },
"types": { "path": "...", "content": "..." },
"hooks": { "path": "...", "content": "..." }
}
}