[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6F7HXS1TRSCFB8997YRGCTH":3,"skill-same:01M6F7HXS1TRSCFB8997YRGCTH":78},{"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":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":55,"commitSha":56,"skillDirectory":57,"forksCount":58,"repositoryHtmlUrl":59,"repositoryHomepageUrl":60,"ownerHtmlUrl":61,"ownerBlogUrl":6,"ownerDescription":62,"updatedAt":63,"install":64,"resources":77},"01M6F7HXS1TRSCFB8997YRGCTH","attio-sdk-patterns",null,"Production-ready patterns for the Attio REST API: typed client,\nretry with backoff, pagination iterators, and multi-tenant factory.\nTrigger: \"attio SDK patterns\", \"attio best practices\",\n\"attio client wrapper\", \"idiomatic attio\", \"attio TypeScript patterns\".","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",66,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fjeremylongshore\u002Fclaude-code-plugins-plus-skills\u002Fattio-sdk-patterns\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"sdk","attio sdk patterns","patterns","attio","saas","api","typescript patterns","read","write","edit","ready","Wrapper","best practices","code","crm","io","trigger","retry","backoff","typescript","2026-11-10 10:12:30",false,"---\nname: attio-sdk-patterns\ndescription: |\n  Production-ready patterns for the Attio REST API: typed client,\n  retry with backoff, pagination iterators, and multi-tenant factory.\n  Trigger: \"attio SDK patterns\", \"attio best practices\",\n  \"attio client wrapper\", \"idiomatic attio\", \"attio TypeScript patterns\".\nallowed-tools: Read, Write, Edit\nversion: 1.0.0\nlicense: MIT\nauthor: Jeremy Longshore \u003Cjeremy@intentsolutions.io>\ntags: [saas, crm, attio]\ncompatible-with: claude-code\n---\n\n# Attio SDK Patterns\n\n## Overview\n\nThere is no official Attio Node.js SDK. The API is a clean REST\u002FJSON interface at `https:\u002F\u002Fapi.attio.com\u002Fv2`. These patterns wrap `fetch` into a production-grade typed client with retry, pagination, and error normalization.\n\n## Prerequisites\n\n- Node.js 18+ (native `fetch`)\n- TypeScript 5+\n- Completed `attio-install-auth`\n\n## Instructions\n\n### Pattern 1: Typed Client with Error Normalization\n\n```typescript\n\u002F\u002F src\u002Fattio\u002Fclient.ts\nconst ATTIO_BASE = \"https:\u002F\u002Fapi.attio.com\u002Fv2\";\n\nexport class AttioApiError extends Error {\n  constructor(\n    public statusCode: number,\n    public type: string,\n    public code: string,\n    message: string\n  ) {\n    super(message);\n    this.name = \"AttioApiError\";\n  }\n\n  get retryable(): boolean {\n    return this.statusCode === 429 || this.statusCode >= 500;\n  }\n}\n\nexport class AttioClient {\n  constructor(private apiKey: string) {}\n\n  async request\u003CT>(\n    method: string,\n    path: string,\n    body?: Record\u003Cstring, unknown>\n  ): Promise\u003CT> {\n    const res = await fetch(`${ATTIO_BASE}${path}`, {\n      method,\n      headers: {\n        Authorization: `Bearer ${this.apiKey}`,\n        \"Content-Type\": \"application\u002Fjson\",\n      },\n      body: body ? JSON.stringify(body) : undefined,\n    });\n\n    if (!res.ok) {\n      const err = await res.json().catch(() => ({}));\n      throw new AttioApiError(\n        res.status,\n        err.type || \"unknown\",\n        err.code || \"unknown\",\n        err.message || `HTTP ${res.status}`\n      );\n    }\n\n    return res.json() as Promise\u003CT>;\n  }\n\n  \u002F\u002F Convenience methods for common HTTP verbs\n  get\u003CT>(path: string) { return this.request\u003CT>(\"GET\", path); }\n  post\u003CT>(path: string, body: Record\u003Cstring, unknown>) { return this.request\u003CT>(\"POST\", path, body); }\n  patch\u003CT>(path: string, body: Record\u003Cstring, unknown>) { return this.request\u003CT>(\"PATCH\", path, body); }\n  put\u003CT>(path: string, body: Record\u003Cstring, unknown>) { return this.request\u003CT>(\"PUT\", path, body); }\n  delete\u003CT>(path: string) { return this.request\u003CT>(\"DELETE\", path); }\n}\n```\n\n### Pattern 2: Retry with Exponential Backoff\n\n```typescript\n\u002F\u002F src\u002Fattio\u002Fretry.ts\nexport async function withRetry\u003CT>(\n  operation: () => Promise\u003CT>,\n  config = { maxRetries: 4, baseMs: 1000, maxMs: 30000 }\n): Promise\u003CT> {\n  for (let attempt = 0; attempt \u003C= config.maxRetries; attempt++) {\n    try {\n      return await operation();\n    } catch (err) {\n      if (attempt === config.maxRetries) throw err;\n\n      \u002F\u002F Only retry on rate limits (429) and server errors (5xx)\n      if (err instanceof AttioApiError && !err.retryable) throw err;\n\n      const delay = Math.min(\n        config.baseMs * Math.pow(2, attempt) + Math.random() * 500,\n        config.maxMs\n      );\n      await new Promise((r) => setTimeout(r, delay));\n    }\n  }\n  throw new Error(\"Unreachable\");\n}\n\n\u002F\u002F Usage\nconst people = await withRetry(() =>\n  client.post(\"\u002Fobjects\u002Fpeople\u002Frecords\u002Fquery\", { limit: 50 })\n);\n```\n\n### Pattern 3: Cursor-Based Pagination Iterator\n\nAttio uses cursor-based pagination. The initial request omits `offset`; responses include `pagination.next_cursor`.\n\n```typescript\n\u002F\u002F src\u002Fattio\u002Fpaginate.ts\nexport async function* paginate\u003CT>(\n  client: AttioClient,\n  path: string,\n  body: Record\u003Cstring, unknown> = {},\n  pageSize = 100\n): AsyncGenerator\u003CT> {\n  let offset = 0;\n  let hasMore = true;\n\n  while (hasMore) {\n    const res = await withRetry(() =>\n      client.post\u003C{ data: T[] }>(path, {\n        ...body,\n        limit: pageSize,\n        offset,\n      })\n    );\n\n    for (const item of res.data) {\n      yield item;\n    }\n\n    hasMore = res.data.length === pageSize;\n    offset += pageSize;\n  }\n}\n\n\u002F\u002F Usage: iterate all companies\nfor await (const company of paginate(client, \"\u002Fobjects\u002Fcompanies\u002Frecords\u002Fquery\")) {\n  console.log(company);\n}\n```\n\n### Pattern 4: Singleton with Lazy Init\n\n```typescript\n\u002F\u002F src\u002Fattio\u002Fsingleton.ts\nlet _client: AttioClient | null = null;\n\nexport function getClient(): AttioClient {\n  if (!_client) {\n    const key = process.env.ATTIO_API_KEY;\n    if (!key) throw new Error(\"ATTIO_API_KEY not set\");\n    _client = new AttioClient(key);\n  }\n  return _client;\n}\n```\n\n### Pattern 5: Multi-Tenant Factory\n\n```typescript\n\u002F\u002F src\u002Fattio\u002Ffactory.ts\nconst tenantClients = new Map\u003Cstring, AttioClient>();\n\nexport function getClientForTenant(tenantId: string): AttioClient {\n  if (!tenantClients.has(tenantId)) {\n    const key = getTenantApiKey(tenantId); \u002F\u002F from DB or secrets manager\n    tenantClients.set(tenantId, new AttioClient(key));\n  }\n  return tenantClients.get(tenantId)!;\n}\n```\n\n### Pattern 6: Response Validation with Zod\n\n```typescript\nimport { z } from \"zod\";\n\nconst AttioPersonSchema = z.object({\n  id: z.object({\n    object_id: z.string(),\n    record_id: z.string(),\n  }),\n  created_at: z.string(),\n  values: z.object({\n    name: z.array(z.object({\n      first_name: z.string().nullable(),\n      last_name: z.string().nullable(),\n      full_name: z.string().nullable(),\n    })),\n    email_addresses: z.array(z.object({\n      email_address: z.string(),\n    })),\n  }).passthrough(),\n});\n\n\u002F\u002F Validated fetch\nconst raw = await client.post(\"\u002Fobjects\u002Fpeople\u002Frecords\u002Fquery\", { limit: 1 });\nconst person = AttioPersonSchema.parse(raw.data[0]);\n```\n\n## Error Handling\n\n| Pattern | When to Use | Benefit |\n|---------|------------|---------|\n| `AttioApiError` class | All API calls | Typed error with `retryable` flag |\n| `withRetry` wrapper | Any mutating or critical read | Auto-retry on 429\u002F5xx |\n| Zod validation | Parsing API responses | Catches schema drift at runtime |\n| Multi-tenant factory | SaaS with per-customer tokens | Isolates credentials |\n\n## Resources\n\n- [Attio REST API Overview](https:\u002F\u002Fdocs.attio.com\u002Frest-api\u002Foverview)\n- [Attio Pagination Guide](https:\u002F\u002Fdocs.attio.com\u002Frest-api\u002Fguides\u002Fpagination)\n- [Attio Slugs and IDs](https:\u002F\u002Fdocs.attio.com\u002Fdocs\u002Fslugs-and-ids)\n- [Zod Documentation](https:\u002F\u002Fzod.dev\u002F)\n\n## Next Steps\n\nApply these patterns in `attio-core-workflow-a` (records CRUD) and `attio-core-workflow-b` (lists and entries).\n\n","# Attio SDK Patterns\n\n## Overview\n\nThere is no official Attio Node.js SDK. The API is a clean REST\u002FJSON interface at `https:\u002F\u002Fapi.attio.com\u002Fv2`. These patterns wrap `fetch` into a production-grade typed client with retry, pagination, and error normalization.\n\n## Prerequisites\n\n- Node.js 18+ (native `fetch`)\n- TypeScript 5+\n- Completed `attio-install-auth`\n\n## Instructions\n\n### Pattern 1: Typed Client with Error Normalization\n\n```typescript\n\u002F\u002F src\u002Fattio\u002Fclient.ts\nconst ATTIO_BASE = \"https:\u002F\u002Fapi.attio.com\u002Fv2\";\n\nexport class AttioApiError extends Error {\n  constructor(\n    public statusCode: number,\n    public type: string,\n    public code: string,\n    message: string\n  ) {\n    super(message);\n    this.name = \"AttioApiError\";\n  }\n\n  get retryable(): boolean {\n    return this.statusCode === 429 || this.statusCode >= 500;\n  }\n}\n\nexport class AttioClient {\n  constructor(private apiKey: string) {}\n\n  async request\u003CT>(\n    method: string,\n    path: string,\n    body?: Record\u003Cstring, unknown>\n  ): Promise\u003CT> {\n    const res = await fetch(`${ATTIO_BASE}${path}`, {\n      method,\n      headers: {\n        Authorization: `Bearer ${this.apiKey}`,\n        \"Content-Type\": \"application\u002Fjson\",\n      },\n      body: body ? JSON.stringify(body) : undefined,\n    });\n\n    if (!res.ok) {\n      const err = await res.json().catch(() => ({}));\n      throw new AttioApiError(\n        res.status,\n        err.type || \"unknown\",\n        err.code || \"unknown\",\n        err.message || `HTTP ${res.status}`\n      );\n    }\n\n    return res.json() as Promise\u003CT>;\n  }\n\n  \u002F\u002F Convenience methods for common HTTP verbs\n  get\u003CT>(path: string) { return this.request\u003CT>(\"GET\", path); }\n  post\u003CT>(path: string, body: Record\u003Cstring, unknown>) { return this.request\u003CT>(\"POST\", path, body); }\n  patch\u003CT>(path: string, body: Record\u003Cstring, unknown>) { return this.request\u003CT>(\"PATCH\", path, body); }\n  put\u003CT>(path: string, body: Record\u003Cstring, unknown>) { return this.request\u003CT>(\"PUT\", path, body); }\n  delete\u003CT>(path: string) { return this.request\u003CT>(\"DELETE\", path); }\n}\n```\n\n### Pattern 2: Retry with Exponential Backoff\n\n```typescript\n\u002F\u002F src\u002Fattio\u002Fretry.ts\nexport async function withRetry\u003CT>(\n  operation: () => Promise\u003CT>,\n  config = { maxRetries: 4, baseMs: 1000, maxMs: 30000 }\n): Promise\u003CT> {\n  for (let attempt = 0; attempt \u003C= config.maxRetries; attempt++) {\n    try {\n      return await operation();\n    } catch (err) {\n      if (attempt === config.maxRetries) throw err;\n\n      \u002F\u002F Only retry on rate limits (429) and server errors (5xx)\n      if (err instanceof AttioApiError && !err.retryable) throw err;\n\n      const delay = Math.min(\n        config.baseMs * Math.pow(2, attempt) + Math.random() * 500,\n        config.maxMs\n      );\n      await new Promise((r) => setTimeout(r, delay));\n    }\n  }\n  throw new Error(\"Unreachable\");\n}\n\n\u002F\u002F Usage\nconst people = await withRetry(() =>\n  client.post(\"\u002Fobjects\u002Fpeople\u002Frecords\u002Fquery\", { limit: 50 })\n);\n```\n\n### Pattern 3: Cursor-Based Pagination Iterator\n\nAttio uses cursor-based pagination. The initial request omits `offset`; responses include `pagination.next_cursor`.\n\n```typescript\n\u002F\u002F src\u002Fattio\u002Fpaginate.ts\nexport async function* paginate\u003CT>(\n  client: AttioClient,\n  path: string,\n  body: Record\u003Cstring, unknown> = {},\n  pageSize = 100\n): AsyncGenerator\u003CT> {\n  let offset = 0;\n  let hasMore = true;\n\n  while (hasMore) {\n    const res = await withRetry(() =>\n      client.post\u003C{ data: T[] }>(path, {\n        ...body,\n        limit: pageSize,\n        offset,\n      })\n    );\n\n    for (const item of res.data) {\n      yield item;\n    }\n\n    hasMore = res.data.length === pageSize;\n    offset += pageSize;\n  }\n}\n\n\u002F\u002F Usage: iterate all companies\nfor await (const company of paginate(client, \"\u002Fobjects\u002Fcompanies\u002Frecords\u002Fquery\")) {\n  console.log(company);\n}\n```\n\n### Pattern 4: Singleton with Lazy Init\n\n```typescript\n\u002F\u002F src\u002Fattio\u002Fsingleton.ts\nlet _client: AttioClient | null = null;\n\nexport function getClient(): AttioClient {\n  if (!_client) {\n    const key = process.env.ATTIO_API_KEY;\n    if (!key) throw new Error(\"ATTIO_API_KEY not set\");\n    _client = new AttioClient(key);\n  }\n  return _client;\n}\n```\n\n### Pattern 5: Multi-Tenant Factory\n\n```typescript\n\u002F\u002F src\u002Fattio\u002Ffactory.ts\nconst tenantClients = new Map\u003Cstring, AttioClient>();\n\nexport function getClientForTenant(tenantId: string): AttioClient {\n  if (!tenantClients.has(tenantId)) {\n    const key = getTenantApiKey(tenantId); \u002F\u002F from DB or secrets manager\n    tenantClients.set(tenantId, new AttioClient(key));\n  }\n  return tenantClients.get(tenantId)!;\n}\n```\n\n### Pattern 6: Response Validation with Zod\n\n```typescript\nimport { z } from \"zod\";\n\nconst AttioPersonSchema = z.object({\n  id: z.object({\n    object_id: z.string(),\n    record_id: z.string(),\n  }),\n  created_at: z.string(),\n  values: z.object({\n    name: z.array(z.object({\n      first_name: z.string().nullable(),\n      last_name: z.string().nullable(),\n      full_name: z.string().nullable(),\n    })),\n    email_addresses: z.array(z.object({\n      email_address: z.string(),\n    })),\n  }).passthrough(),\n});\n\n\u002F\u002F Validated fetch\nconst raw = await client.post(\"\u002Fobjects\u002Fpeople\u002Frecords\u002Fquery\", { limit: 1 });\nconst person = AttioPersonSchema.parse(raw.data[0]);\n```\n\n## Error Handling\n\n| Pattern | When to Use | Benefit |\n|---------|------------|---------|\n| `AttioApiError` class | All API calls | Typed error with `retryable` flag |\n| `withRetry` wrapper | Any mutating or critical read | Auto-retry on 429\u002F5xx |\n| Zod validation | Parsing API responses | Catches schema drift at runtime |\n| Multi-tenant factory | SaaS with per-customer tokens | Isolates credentials |\n\n## Resources\n\n- [Attio REST API Overview](https:\u002F\u002Fdocs.attio.com\u002Frest-api\u002Foverview)\n- [Attio Pagination Guide](https:\u002F\u002Fdocs.attio.com\u002Frest-api\u002Fguides\u002Fpagination)\n- [Attio Slugs and IDs](https:\u002F\u002Fdocs.attio.com\u002Fdocs\u002Fslugs-and-ids)\n- [Zod Documentation](https:\u002F\u002Fzod.dev\u002F)\n\n## Next Steps\n\nApply these patterns in `attio-core-workflow-a` (records CRUD) and `attio-core-workflow-b` (lists and entries).\n\n",{"name":5,"tags":49,"author":50,"license":15,"version":51,"description":52,"allowed-tools":53,"compatible-with":54},[28,38,27],"Jeremy Longshore \u003Cjeremy@intentsolutions.io>","1.0.0","Production-ready patterns for the Attio REST API: typed client,\nretry with backoff, pagination iterators, and multi-tenant factory.\nTrigger: \"attio SDK patterns\", \"attio best practices\",\n\"attio client wrapper\", \"idiomatic attio\", \"attio TypeScript patterns\".\n","Read, Write, Edit","claude-code","main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Fjeremylongshore\u002Fclaude-code-plugins-plus-skills\u002Fattio-sdk-patterns",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":65,"prompt":75,"zipAvailable":76},[66,69,72],{"tool":67,"command":68},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill attio-sdk-patterns",{"tool":70,"command":71},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill attio-sdk-patterns",{"tool":73,"command":74},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill attio-sdk-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fjeremylongshore\u002Fclaude-code-plugins-plus-skills\u002Fattio-sdk-patterns\u002FSKILL.md",true,[],[79,93,103,111,117,124],{"skillNo":80,"name":81,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":82,"categories":83,"keywords":89,"publishedAt":44},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[84],{"categoryNo":85,"categoryName":86,"taxonomyType":87,"taxonomyTypeDesc":88},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[90,91,92],"model","model hierarchy","model hierarchy skill",{"skillNo":94,"name":95,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":99,"publishedAt":44},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[98],{"categoryNo":85,"categoryName":86,"taxonomyType":87,"taxonomyTypeDesc":88},[100,101,102],"MCP","zoom","zoom mcp",{"skillNo":104,"name":105,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":106,"categories":107,"keywords":108,"publishedAt":44},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[24,109,110,101],"zoom apps sdk","apps",{"skillNo":112,"name":113,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":114,"categories":115,"keywords":116,"publishedAt":44},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[113],{"skillNo":118,"name":119,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":120,"categories":121,"keywords":123,"publishedAt":44},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[122],{"categoryNo":85,"categoryName":86,"taxonomyType":87,"taxonomyTypeDesc":88},[119],{"skillNo":125,"name":126,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":127,"categories":128,"keywords":129,"publishedAt":44},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[126]]