[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6HGXT2FGAX11FDF1CCXW465":3,"skill-same:01M6HGXT2FGAX11FDF1CCXW465":70},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":42,"linkOnly":43,"markdownContent":44,"markdownBody":45,"frontMatter":46,"refName":48,"commitSha":49,"skillDirectory":50,"forksCount":51,"repositoryHtmlUrl":52,"repositoryHomepageUrl":6,"ownerHtmlUrl":53,"ownerBlogUrl":6,"ownerDescription":54,"updatedAt":55,"install":56,"resources":69},"01M6HGXT2FGAX11FDF1CCXW465","expo-api-routes",null,"Guidelines for creating API routes in Expo Router with EAS Hosting","HenriqueMC17\u002Fagente-core","HenriqueMC17","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F206460478?v=4","01M6HB63HBBF18AC4H09XTB549","Henrique Monteiro Cardoso","01M6HB63NGSQXWKWCFWW2B20W0",1,"MIT","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Fgeneral\u002Fexpo-api-routes\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[29,30,31,32,33,34,35,36,37,38,39,40,41],"expo api routes","api","expo","guidelines","router","hosting","general","community","expo router","with","eas hosting","for","unknown","2026-11-10 10:12:30",false,"---\nname: expo-api-routes\ndescription: Guidelines for creating API routes in Expo Router with EAS Hosting\nrisk: unknown\nsource: community\nversion: 1.0.0\nlicense: MIT\ncategory: general\n---\n## When to Use API Routes\n\nUse API routes when you need:\n\n- **Server-side secrets** — API keys, database credentials, or tokens that must never reach the client\n- **Database operations** — Direct database queries that shouldn't be exposed\n- **Third-party API proxies** — Hide API keys when calling external services (OpenAI, Stripe, etc.)\n- **Server-side validation** — Validate data before database writes\n- **Webhook endpoints** — Receive callbacks from services like Stripe or GitHub\n- **Rate limiting** — Control access at the server level\n- **Heavy computation** — Offload processing that would be slow on mobile\n\n## When NOT to Use API Routes\n\nAvoid API routes when:\n\n- **Data is already public** — Use direct fetch to public APIs instead\n- **No secrets required** — Static data or client-safe operations\n- **Real-time updates needed** — Use WebSockets or services like Supabase Realtime\n- **Simple CRUD** — Consider Firebase, Supabase, or Convex for managed backends\n- **File uploads** — Use direct-to-storage uploads (S3 presigned URLs, Cloudflare R2)\n- **Authentication only** — Use Clerk, Auth0, or Firebase Auth instead\n\n## File Structure\n\nAPI routes live in the `app` directory with `+api.ts` suffix:\n\n```\napp\u002F\n  api\u002F\n    hello+api.ts          → GET \u002Fapi\u002Fhello\n    users+api.ts          → \u002Fapi\u002Fusers\n    users\u002F[id]+api.ts     → \u002Fapi\u002Fusers\u002F:id\n  (tabs)\u002F\n    index.tsx\n```\n\n## Basic API Route\n\n```ts\n\u002F\u002F app\u002Fapi\u002Fhello+api.ts\nexport function GET(request: Request) {\n  return Response.json({ message: \"Hello from Expo!\" });\n}\n```\n\n## HTTP Methods\n\nExport named functions for each HTTP method:\n\n```ts\n\u002F\u002F app\u002Fapi\u002Fitems+api.ts\nexport function GET(request: Request) {\n  return Response.json({ items: [] });\n}\n\nexport async function POST(request: Request) {\n  const body = await request.json();\n  return Response.json({ created: body }, { status: 201 });\n}\n\nexport async function PUT(request: Request) {\n  const body = await request.json();\n  return Response.json({ updated: body });\n}\n\nexport async function DELETE(request: Request) {\n  return new Response(null, { status: 204 });\n}\n```\n\n## Dynamic Routes\n\n```ts\n\u002F\u002F app\u002Fapi\u002Fusers\u002F[id]+api.ts\nexport function GET(request: Request, { id }: { id: string }) {\n  return Response.json({ userId: id });\n}\n```\n\n## Request Handling\n\n### Query Parameters\n\n```ts\nexport function GET(request: Request) {\n  const url = new URL(request.url);\n  const page = url.searchParams.get(\"page\") ?? \"1\";\n  const limit = url.searchParams.get(\"limit\") ?? \"10\";\n\n  return Response.json({ page, limit });\n}\n```\n\n### Headers\n\n```ts\nexport function GET(request: Request) {\n  const auth = request.headers.get(\"Authorization\");\n\n  if (!auth) {\n    return Response.json({ error: \"Unauthorized\" }, { status: 401 });\n  }\n\n  return Response.json({ authenticated: true });\n}\n```\n\n### JSON Body\n\n```ts\nexport async function POST(request: Request) {\n  const { email, password } = await request.json();\n\n  if (!email || !password) {\n    return Response.json({ error: \"Missing fields\" }, { status: 400 });\n  }\n\n  return Response.json({ success: true });\n}\n```\n\n## Environment Variables\n\nUse `process.env` for server-side secrets:\n\n```ts\n\u002F\u002F app\u002Fapi\u002Fai+api.ts\nexport async function POST(request: Request) {\n  const { prompt } = await request.json();\n\n  const response = await fetch(\"https:\u002F\u002Fapi.openai.com\u002Fv1\u002Fchat\u002Fcompletions\", {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"application\u002Fjson\",\n      Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,\n    },\n    body: JSON.stringify({\n      model: \"gpt-4\",\n      messages: [{ role: \"user\", content: prompt }],\n    }),\n  });\n\n  const data = await response.json();\n  return Response.json(data);\n}\n```\n\nSet environment variables:\n\n- **Local**: Create `.env` file (never commit)\n- **EAS Hosting**: Use `eas env:create` or Expo dashboard\n\n## CORS Headers\n\nAdd CORS for web clients:\n\n```ts\nconst corsHeaders = {\n  \"Access-Control-Allow-Origin\": \"*\",\n  \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n  \"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n};\n\nexport function OPTIONS() {\n  return new Response(null, { headers: corsHeaders });\n}\n\nexport function GET() {\n  return Response.json({ data: \"value\" }, { headers: corsHeaders });\n}\n```\n\n## Error Handling\n\n```ts\nexport async function POST(request: Request) {\n  try {\n    const body = await request.json();\n    \u002F\u002F Process...\n    return Response.json({ success: true });\n  } catch (error) {\n    console.error(\"API error:\", error);\n    return Response.json({ error: \"Internal server error\" }, { status: 500 });\n  }\n}\n```\n\n## Testing Locally\n\nStart the development server with API routes:\n\n```bash\nnpx expo serve\n```\n\nThis starts a local server at `http:\u002F\u002Flocalhost:8081` with full API route support.\n\nTest with curl:\n\n```bash\ncurl http:\u002F\u002Flocalhost:8081\u002Fapi\u002Fhello\ncurl -X POST http:\u002F\u002Flocalhost:8081\u002Fapi\u002Fusers -H \"Content-Type: application\u002Fjson\" -d '{\"name\":\"Test\"}'\n```\n\n## Deployment to EAS Hosting\n\n### Prerequisites\n\n```bash\nnpm install -g eas-cli\neas login\n```\n\n### Deploy\n\n```bash\neas deploy\n```\n\nThis builds and deploys your API routes to EAS Hosting (Cloudflare Workers).\n\n### Environment Variables for Production\n\n```bash\n# Create a secret\neas env:create --name OPENAI_API_KEY --value sk-xxx --environment production\n\n# Or use the Expo dashboard\n```\n\n### Custom Domain\n\nConfigure in `eas.json` or Expo dashboard.\n\n## EAS Hosting Runtime (Cloudflare Workers)\n\nAPI routes run on Cloudflare Workers. Key limitations:\n\n### Missing\u002FLimited APIs\n\n- **No Node.js filesystem** — `fs` module unavailable\n- **No native Node modules** — Use Web APIs or polyfills\n- **Limited execution time** — 30 second timeout for CPU-intensive tasks\n- **No persistent connections** — WebSockets require Durable Objects\n- **fetch is available** — Use standard fetch for HTTP requests\n\n### Use Web APIs Instead\n\n```ts\n\u002F\u002F Use Web Crypto instead of Node crypto\nconst hash = await crypto.subtle.digest(\n  \"SHA-256\",\n  new TextEncoder().encode(\"data\")\n);\n\n\u002F\u002F Use fetch instead of node-fetch\nconst response = await fetch(\"https:\u002F\u002Fapi.example.com\");\n\n\u002F\u002F Use Response\u002FRequest (already available)\nreturn new Response(JSON.stringify(data), {\n  headers: { \"Content-Type\": \"application\u002Fjson\" },\n});\n```\n\n### Database Options\n\nSince filesystem is unavailable, use cloud databases:\n\n- **Cloudflare D1** — SQLite at the edge\n- **Turso** — Distributed SQLite\n- **PlanetScale** — Serverless MySQL\n- **Supabase** — Postgres with REST API\n- **Neon** — Serverless Postgres\n\nExample with Turso:\n\n```ts\n\u002F\u002F app\u002Fapi\u002Fusers+api.ts\nimport { createClient } from \"@libsql\u002Fclient\u002Fweb\";\n\nconst db = createClient({\n  url: process.env.TURSO_URL!,\n  authToken: process.env.TURSO_AUTH_TOKEN!,\n});\n\nexport async function GET() {\n  const result = await db.execute(\"SELECT * FROM users\");\n  return Response.json(result.rows);\n}\n```\n\n## Calling API Routes from Client\n\n```ts\n\u002F\u002F From React Native components\nconst response = await fetch(\"\u002Fapi\u002Fhello\");\nconst data = await response.json();\n\n\u002F\u002F With body\nconst response = await fetch(\"\u002Fapi\u002Fusers\", {\n  method: \"POST\",\n  headers: { \"Content-Type\": \"application\u002Fjson\" },\n  body: JSON.stringify({ name: \"John\" }),\n});\n```\n\n## Common Patterns\n\n### Authentication Middleware\n\n```ts\n\u002F\u002F utils\u002Fauth.ts\nexport async function requireAuth(request: Request) {\n  const token = request.headers.get(\"Authorization\")?.replace(\"Bearer \", \"\");\n\n  if (!token) {\n    throw new Response(JSON.stringify({ error: \"Unauthorized\" }), {\n      status: 401,\n      headers: { \"Content-Type\": \"application\u002Fjson\" },\n    });\n  }\n\n  \u002F\u002F Verify token...\n  return { userId: \"123\" };\n}\n\n\u002F\u002F app\u002Fapi\u002Fprotected+api.ts\nimport { requireAuth } from \"..\u002F..\u002Futils\u002Fauth\";\n\nexport async function GET(request: Request) {\n  const { userId } = await requireAuth(request);\n  return Response.json({ userId });\n}\n```\n\n### Proxy External API\n\n```ts\n\u002F\u002F app\u002Fapi\u002Fweather+api.ts\nexport async function GET(request: Request) {\n  const url = new URL(request.url);\n  const city = url.searchParams.get(\"city\");\n\n  const response = await fetch(\n    `https:\u002F\u002Fapi.weather.com\u002Fv1\u002Fcurrent?city=${city}&key=${process.env.WEATHER_API_KEY}`\n  );\n\n  return Response.json(await response.json());\n}\n```\n\n## Rules\n\n- NEVER expose API keys or secrets in client code\n- ALWAYS validate and sanitize user input\n- Use proper HTTP status codes (200, 201, 400, 401, 404, 500)\n- Handle errors gracefully with try\u002Fcatch\n- Keep API routes focused — one responsibility per endpoint\n- Use TypeScript for type safety\n- Log errors server-side for debugging\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.\n","## When to Use API Routes\n\nUse API routes when you need:\n\n- **Server-side secrets** — API keys, database credentials, or tokens that must never reach the client\n- **Database operations** — Direct database queries that shouldn't be exposed\n- **Third-party API proxies** — Hide API keys when calling external services (OpenAI, Stripe, etc.)\n- **Server-side validation** — Validate data before database writes\n- **Webhook endpoints** — Receive callbacks from services like Stripe or GitHub\n- **Rate limiting** — Control access at the server level\n- **Heavy computation** — Offload processing that would be slow on mobile\n\n## When NOT to Use API Routes\n\nAvoid API routes when:\n\n- **Data is already public** — Use direct fetch to public APIs instead\n- **No secrets required** — Static data or client-safe operations\n- **Real-time updates needed** — Use WebSockets or services like Supabase Realtime\n- **Simple CRUD** — Consider Firebase, Supabase, or Convex for managed backends\n- **File uploads** — Use direct-to-storage uploads (S3 presigned URLs, Cloudflare R2)\n- **Authentication only** — Use Clerk, Auth0, or Firebase Auth instead\n\n## File Structure\n\nAPI routes live in the `app` directory with `+api.ts` suffix:\n\n```\napp\u002F\n  api\u002F\n    hello+api.ts          → GET \u002Fapi\u002Fhello\n    users+api.ts          → \u002Fapi\u002Fusers\n    users\u002F[id]+api.ts     → \u002Fapi\u002Fusers\u002F:id\n  (tabs)\u002F\n    index.tsx\n```\n\n## Basic API Route\n\n```ts\n\u002F\u002F app\u002Fapi\u002Fhello+api.ts\nexport function GET(request: Request) {\n  return Response.json({ message: \"Hello from Expo!\" });\n}\n```\n\n## HTTP Methods\n\nExport named functions for each HTTP method:\n\n```ts\n\u002F\u002F app\u002Fapi\u002Fitems+api.ts\nexport function GET(request: Request) {\n  return Response.json({ items: [] });\n}\n\nexport async function POST(request: Request) {\n  const body = await request.json();\n  return Response.json({ created: body }, { status: 201 });\n}\n\nexport async function PUT(request: Request) {\n  const body = await request.json();\n  return Response.json({ updated: body });\n}\n\nexport async function DELETE(request: Request) {\n  return new Response(null, { status: 204 });\n}\n```\n\n## Dynamic Routes\n\n```ts\n\u002F\u002F app\u002Fapi\u002Fusers\u002F[id]+api.ts\nexport function GET(request: Request, { id }: { id: string }) {\n  return Response.json({ userId: id });\n}\n```\n\n## Request Handling\n\n### Query Parameters\n\n```ts\nexport function GET(request: Request) {\n  const url = new URL(request.url);\n  const page = url.searchParams.get(\"page\") ?? \"1\";\n  const limit = url.searchParams.get(\"limit\") ?? \"10\";\n\n  return Response.json({ page, limit });\n}\n```\n\n### Headers\n\n```ts\nexport function GET(request: Request) {\n  const auth = request.headers.get(\"Authorization\");\n\n  if (!auth) {\n    return Response.json({ error: \"Unauthorized\" }, { status: 401 });\n  }\n\n  return Response.json({ authenticated: true });\n}\n```\n\n### JSON Body\n\n```ts\nexport async function POST(request: Request) {\n  const { email, password } = await request.json();\n\n  if (!email || !password) {\n    return Response.json({ error: \"Missing fields\" }, { status: 400 });\n  }\n\n  return Response.json({ success: true });\n}\n```\n\n## Environment Variables\n\nUse `process.env` for server-side secrets:\n\n```ts\n\u002F\u002F app\u002Fapi\u002Fai+api.ts\nexport async function POST(request: Request) {\n  const { prompt } = await request.json();\n\n  const response = await fetch(\"https:\u002F\u002Fapi.openai.com\u002Fv1\u002Fchat\u002Fcompletions\", {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"application\u002Fjson\",\n      Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,\n    },\n    body: JSON.stringify({\n      model: \"gpt-4\",\n      messages: [{ role: \"user\", content: prompt }],\n    }),\n  });\n\n  const data = await response.json();\n  return Response.json(data);\n}\n```\n\nSet environment variables:\n\n- **Local**: Create `.env` file (never commit)\n- **EAS Hosting**: Use `eas env:create` or Expo dashboard\n\n## CORS Headers\n\nAdd CORS for web clients:\n\n```ts\nconst corsHeaders = {\n  \"Access-Control-Allow-Origin\": \"*\",\n  \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n  \"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n};\n\nexport function OPTIONS() {\n  return new Response(null, { headers: corsHeaders });\n}\n\nexport function GET() {\n  return Response.json({ data: \"value\" }, { headers: corsHeaders });\n}\n```\n\n## Error Handling\n\n```ts\nexport async function POST(request: Request) {\n  try {\n    const body = await request.json();\n    \u002F\u002F Process...\n    return Response.json({ success: true });\n  } catch (error) {\n    console.error(\"API error:\", error);\n    return Response.json({ error: \"Internal server error\" }, { status: 500 });\n  }\n}\n```\n\n## Testing Locally\n\nStart the development server with API routes:\n\n```bash\nnpx expo serve\n```\n\nThis starts a local server at `http:\u002F\u002Flocalhost:8081` with full API route support.\n\nTest with curl:\n\n```bash\ncurl http:\u002F\u002Flocalhost:8081\u002Fapi\u002Fhello\ncurl -X POST http:\u002F\u002Flocalhost:8081\u002Fapi\u002Fusers -H \"Content-Type: application\u002Fjson\" -d '{\"name\":\"Test\"}'\n```\n\n## Deployment to EAS Hosting\n\n### Prerequisites\n\n```bash\nnpm install -g eas-cli\neas login\n```\n\n### Deploy\n\n```bash\neas deploy\n```\n\nThis builds and deploys your API routes to EAS Hosting (Cloudflare Workers).\n\n### Environment Variables for Production\n\n```bash\n# Create a secret\neas env:create --name OPENAI_API_KEY --value sk-xxx --environment production\n\n# Or use the Expo dashboard\n```\n\n### Custom Domain\n\nConfigure in `eas.json` or Expo dashboard.\n\n## EAS Hosting Runtime (Cloudflare Workers)\n\nAPI routes run on Cloudflare Workers. Key limitations:\n\n### Missing\u002FLimited APIs\n\n- **No Node.js filesystem** — `fs` module unavailable\n- **No native Node modules** — Use Web APIs or polyfills\n- **Limited execution time** — 30 second timeout for CPU-intensive tasks\n- **No persistent connections** — WebSockets require Durable Objects\n- **fetch is available** — Use standard fetch for HTTP requests\n\n### Use Web APIs Instead\n\n```ts\n\u002F\u002F Use Web Crypto instead of Node crypto\nconst hash = await crypto.subtle.digest(\n  \"SHA-256\",\n  new TextEncoder().encode(\"data\")\n);\n\n\u002F\u002F Use fetch instead of node-fetch\nconst response = await fetch(\"https:\u002F\u002Fapi.example.com\");\n\n\u002F\u002F Use Response\u002FRequest (already available)\nreturn new Response(JSON.stringify(data), {\n  headers: { \"Content-Type\": \"application\u002Fjson\" },\n});\n```\n\n### Database Options\n\nSince filesystem is unavailable, use cloud databases:\n\n- **Cloudflare D1** — SQLite at the edge\n- **Turso** — Distributed SQLite\n- **PlanetScale** — Serverless MySQL\n- **Supabase** — Postgres with REST API\n- **Neon** — Serverless Postgres\n\nExample with Turso:\n\n```ts\n\u002F\u002F app\u002Fapi\u002Fusers+api.ts\nimport { createClient } from \"@libsql\u002Fclient\u002Fweb\";\n\nconst db = createClient({\n  url: process.env.TURSO_URL!,\n  authToken: process.env.TURSO_AUTH_TOKEN!,\n});\n\nexport async function GET() {\n  const result = await db.execute(\"SELECT * FROM users\");\n  return Response.json(result.rows);\n}\n```\n\n## Calling API Routes from Client\n\n```ts\n\u002F\u002F From React Native components\nconst response = await fetch(\"\u002Fapi\u002Fhello\");\nconst data = await response.json();\n\n\u002F\u002F With body\nconst response = await fetch(\"\u002Fapi\u002Fusers\", {\n  method: \"POST\",\n  headers: { \"Content-Type\": \"application\u002Fjson\" },\n  body: JSON.stringify({ name: \"John\" }),\n});\n```\n\n## Common Patterns\n\n### Authentication Middleware\n\n```ts\n\u002F\u002F utils\u002Fauth.ts\nexport async function requireAuth(request: Request) {\n  const token = request.headers.get(\"Authorization\")?.replace(\"Bearer \", \"\");\n\n  if (!token) {\n    throw new Response(JSON.stringify({ error: \"Unauthorized\" }), {\n      status: 401,\n      headers: { \"Content-Type\": \"application\u002Fjson\" },\n    });\n  }\n\n  \u002F\u002F Verify token...\n  return { userId: \"123\" };\n}\n\n\u002F\u002F app\u002Fapi\u002Fprotected+api.ts\nimport { requireAuth } from \"..\u002F..\u002Futils\u002Fauth\";\n\nexport async function GET(request: Request) {\n  const { userId } = await requireAuth(request);\n  return Response.json({ userId });\n}\n```\n\n### Proxy External API\n\n```ts\n\u002F\u002F app\u002Fapi\u002Fweather+api.ts\nexport async function GET(request: Request) {\n  const url = new URL(request.url);\n  const city = url.searchParams.get(\"city\");\n\n  const response = await fetch(\n    `https:\u002F\u002Fapi.weather.com\u002Fv1\u002Fcurrent?city=${city}&key=${process.env.WEATHER_API_KEY}`\n  );\n\n  return Response.json(await response.json());\n}\n```\n\n## Rules\n\n- NEVER expose API keys or secrets in client code\n- ALWAYS validate and sanitize user input\n- Use proper HTTP status codes (200, 201, 400, 401, 404, 500)\n- Handle errors gracefully with try\u002Fcatch\n- Keep API routes focused — one responsibility per endpoint\n- Use TypeScript for type safety\n- Log errors server-side for debugging\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.\n",{"name":5,"risk":41,"source":36,"license":15,"version":47,"category":35,"description":7},"1.0.0","main","5eea5b3296f4673b5f481e8bcc1ba76281149f16","modules\u002Fgeneral\u002Fexpo-api-routes",0,"https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core","https:\u002F\u002Fgithub.com\u002FHenriqueMC17","Qualquer tecnologia suficientemente avançada é indistinguível da mágica.","2026-09-28 22:40:38",{"source":8,"skillName":5,"commands":57,"prompt":67,"zipAvailable":68},[58,61,64],{"tool":59,"command":60},"npx","npx skills add HenriqueMC17\u002Fagente-core --skill expo-api-routes",{"tool":62,"command":63},"bunx","bunx skills add HenriqueMC17\u002Fagente-core --skill expo-api-routes",{"tool":65,"command":66},"pnpm","pnpm dlx skills add HenriqueMC17\u002Fagente-core --skill expo-api-routes","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Fgeneral\u002Fexpo-api-routes\u002FSKILL.md",true,[],[71,101,126,149,165,186],{"skillNo":72,"name":73,"nameZh":6,"description":74,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":75,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":81,"publishedAt":42},"01M6HPFF0RCN0X6WT5EBSV71GY","validating-backup-integrity-for-recovery","Validate backup integrity through cryptographic hash verification, automated restore testing, corruption detection, and recoverability checks to ensure backups are reliable for disaster recovery and ransomware response scenarios.","Apache-2.0","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Fvalidating-backup-integrity-for-recovery\u002FSKILL.md",[78],{"categoryNo":79,"categoryName":80,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",[82,83,84,85,40,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100],"integrity","backup","recovery","validating backup integrity for recovery","testing","cybersecurity","validate","verification","hash-verification","incident-response","ransomware","detection","t1078","t1490","disaster-recovery","restore","incident","disaster recovery","ransomware response",{"skillNo":102,"name":103,"nameZh":6,"description":104,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":75,"licenseFileUrl":6,"sourceHtmlUrl":105,"categories":106,"keywords":107,"publishedAt":42},"01M6HPFAWJVFK25Q33K3T7WQ8G","triaging-vulnerabilities-with-ssvc-framework","Triage and prioritize vulnerabilities using CISA's Stakeholder-Specific Vulnerability Categorization (SSVC) decision tree framework to produce actionable remediation priorities.","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Ftriaging-vulnerabilities-with-ssvc-framework\u002FSKILL.md",[],[108,109,110,111,38,87,112,113,114,115,116,117,118,119,120,121,122,123,124,125],"vulnerabilities","framework","ssvc","triaging vulnerabilities with ssvc framework","triage and prioritize","CISA","vulnerability-management","risk-management","cvss","remediation","vulnerability","prioritization","decision-tree","prioritize","decision","priorities","actionable","tree",{"skillNo":127,"name":128,"nameZh":6,"description":129,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":75,"licenseFileUrl":6,"sourceHtmlUrl":130,"categories":131,"keywords":132,"publishedAt":42},"01M6HPF6JS9X72WP59094H3ASQ","triaging-security-incident","Performs initial triage of security incidents to determine severity, scope, and required response actions using the NIST SP 800-61r3 and SANS PICERL frameworks. Classifies incidents by type, assigns priority based on business impact, and routes...","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Ftriaging-security-incident\u002FSKILL.md",[],[133,134,98,87,135,136,137,94,95,138,139,140,141,142,143,144,145,146,147,148],"security","triaging security incident","actions","soc","NIST","analysis","severity-classification","incident-triage","SANS-PICERL","SOC-operations","picerl","conversion","isolation","scope","impact","consistency",{"skillNo":150,"name":151,"nameZh":6,"description":152,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":75,"licenseFileUrl":6,"sourceHtmlUrl":153,"categories":154,"keywords":155,"publishedAt":42},"01M6HPF2EX6ZYNYYHKBRJN7GEF","triaging-security-incident-with-ir-playbook","Classify and prioritize security incidents using structured IR playbooks to determine severity, assign response teams, and initiate appropriate response procedures.","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Ftriaging-security-incident-with-ir-playbook\u002FSKILL.md",[],[133,156,157,134,98,38,87,158,136,91,159,160,94,95,161,139,121,162,163,164],"playbook","triaging security incident with ir playbook","teams","IR-playbook","severity","classification","classify","incidents","initiate",{"skillNo":166,"name":167,"nameZh":6,"description":168,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":75,"licenseFileUrl":6,"sourceHtmlUrl":169,"categories":170,"keywords":171,"publishedAt":42},"01M6HPEY9XPGE7X95AG4XJFQAW","triaging-security-alerts-in-splunk","Triages security alerts in Splunk Enterprise Security by classifying severity, investigating notable events, correlating related telemetry, and making escalation or closure decisions using SPL queries and the Incident Review dashboard. Use when...","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Ftriaging-security-alerts-in-splunk\u002FSKILL.md",[],[133,172,173,174,175,176,87,177,178,179,136,180,94,181,182,183,142,184,98,185],"security alerts","splunk","triaging security alerts in splunk","alerts","review","siem","dashboard","search","correlation-search","t1566","notable-events","incident-review","cm","de",{"skillNo":187,"name":188,"nameZh":6,"description":189,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":75,"licenseFileUrl":6,"sourceHtmlUrl":190,"categories":191,"keywords":192,"publishedAt":42},"01M6HPET6XGEPEJPN7V032JGZ0","tracking-threat-actor-infrastructure","Threat actor infrastructure tracking involves monitoring and mapping adversary-controlled assets including command-and-control (C2) servers, phishing domains, exploit kit hosts, bulletproof hosting, a","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Ftracking-threat-actor-infrastructure\u002FSKILL.md",[],[193,194,195,196,87,197,198,199,200,201,202,181,203,204,184,205,185,206,207,208],"infrastructure","tracking threat actor infrastructure","tracking","threat","monitoring","mitre-attack","threat-actor","threat-intelligence","command-and-control","dns","command","exploit","intelligence","domains","kit","hosts"]