[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CHC229742DSVV30T6EB2WD":3,"skill-same:01M6CHC229742DSVV30T6EB2WD":75},{"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":18,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":52,"commitSha":53,"skillDirectory":54,"forksCount":55,"repositoryHtmlUrl":56,"repositoryHomepageUrl":6,"ownerHtmlUrl":57,"ownerBlogUrl":58,"ownerDescription":59,"updatedAt":60,"install":61,"resources":74},"01M6CHC229742DSVV30T6EB2WD","apollo-migration-deep-dive",null,"Comprehensive Apollo.io migration strategies.\nUse when migrating from other CRMs to Apollo, consolidating data sources,\nor executing large-scale data migrations.\nTrigger with phrases like \"apollo migration\", \"migrate to apollo\",\n\"apollo data import\", \"crm to apollo\", \"apollo migration strategy\".","Dicklesworthstone\u002Fpi_agent_rust","Dicklesworthstone","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F35050222?v=4","01M6CG26AR942CSVMN1M5E3DSE","Jeff Emanuel","01M6CG26EPP71PSHW1VDS71121",1981,"MIT","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fapollo-pack\u002Fskills\u002Fapollo-migration-deep-dive\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"deep dive","deep","migration","apollo","apollo migration deep dive","when","data","data sources","data import","migration strategy","sources","io","strategies","crm","migrations","use","strategy","edit","write","read","curl","migrate","Bash","kubectl","2026-11-10 10:12:30",false,"---\nname: apollo-migration-deep-dive\ndescription: |\n  Comprehensive Apollo.io migration strategies.\n  Use when migrating from other CRMs to Apollo, consolidating data sources,\n  or executing large-scale data migrations.\n  Trigger with phrases like \"apollo migration\", \"migrate to apollo\",\n  \"apollo data import\", \"crm to apollo\", \"apollo migration strategy\".\nallowed-tools: Read, Write, Edit, Bash(kubectl:*), Bash(curl:*)\nversion: 1.0.0\nlicense: MIT\nauthor: Jeremy Longshore \u003Cjeremy@intentsolutions.io>\n---\n\n# Apollo Migration Deep Dive\n\n## Overview\nComprehensive guide for migrating to Apollo.io from other CRMs and data sources, including data mapping, validation, and rollback strategies.\n\n## Migration Planning\n\n### Pre-Migration Assessment\n\n```typescript\n\u002F\u002F scripts\u002Fmigration-assessment.ts\ninterface MigrationAssessment {\n  source: {\n    system: string;\n    recordCount: number;\n    dataQuality: DataQualityReport;\n    fieldMapping: FieldMappingAnalysis;\n  };\n  target: {\n    apolloPlan: string;\n    creditBudget: number;\n    apiLimits: APILimits;\n  };\n  risk: {\n    level: 'low' | 'medium' | 'high';\n    factors: string[];\n    mitigations: string[];\n  };\n  timeline: {\n    estimatedDuration: string;\n    phases: Phase[];\n  };\n}\n\nasync function assessMigration(sourceConfig: any): Promise\u003CMigrationAssessment> {\n  \u002F\u002F Analyze source data\n  const sourceAnalysis = await analyzeSourceData(sourceConfig);\n\n  \u002F\u002F Check Apollo capacity\n  const apolloCapacity = await checkApolloCapacity();\n\n  \u002F\u002F Calculate risks\n  const risks = calculateRisks(sourceAnalysis, apolloCapacity);\n\n  \u002F\u002F Estimate timeline\n  const timeline = estimateTimeline(sourceAnalysis, apolloCapacity);\n\n  return {\n    source: sourceAnalysis,\n    target: apolloCapacity,\n    risk: risks,\n    timeline,\n  };\n}\n\nasync function analyzeSourceData(config: any): Promise\u003CSourceAnalysis> {\n  const records = await fetchSourceRecords(config);\n\n  return {\n    system: config.system,\n    recordCount: records.length,\n    dataQuality: {\n      emailValid: records.filter(r => isValidEmail(r.email)).length \u002F records.length,\n      emailPresent: records.filter(r => r.email).length \u002F records.length,\n      phonePresent: records.filter(r => r.phone).length \u002F records.length,\n      companyPresent: records.filter(r => r.company).length \u002F records.length,\n      duplicates: findDuplicates(records).length,\n    },\n    fieldMapping: analyzeFields(records),\n  };\n}\n```\n\n### Field Mapping\n\n```typescript\n\u002F\u002F src\u002Fmigration\u002Ffield-mapper.ts\ninterface FieldMapping {\n  sourceField: string;\n  targetField: string;\n  transform?: (value: any) => any;\n  required: boolean;\n  validation?: (value: any) => boolean;\n}\n\nconst SALESFORCE_TO_APOLLO: FieldMapping[] = [\n  {\n    sourceField: 'Email',\n    targetField: 'email',\n    required: true,\n    validation: isValidEmail,\n  },\n  {\n    sourceField: 'FirstName',\n    targetField: 'first_name',\n    required: false,\n  },\n  {\n    sourceField: 'LastName',\n    targetField: 'last_name',\n    required: false,\n  },\n  {\n    sourceField: 'Title',\n    targetField: 'title',\n    required: false,\n    transform: normalizeTitle,\n  },\n  {\n    sourceField: 'Phone',\n    targetField: 'phone',\n    required: false,\n    transform: normalizePhone,\n  },\n  {\n    sourceField: 'Account.Name',\n    targetField: 'organization_name',\n    required: false,\n  },\n  {\n    sourceField: 'Account.Website',\n    targetField: 'organization_domain',\n    transform: extractDomain,\n    required: false,\n  },\n  {\n    sourceField: 'LinkedIn_URL__c',\n    targetField: 'linkedin_url',\n    required: false,\n    validation: isValidLinkedInUrl,\n  },\n];\n\nconst HUBSPOT_TO_APOLLO: FieldMapping[] = [\n  { sourceField: 'properties.email', targetField: 'email', required: true },\n  { sourceField: 'properties.firstname', targetField: 'first_name', required: false },\n  { sourceField: 'properties.lastname', targetField: 'last_name', required: false },\n  { sourceField: 'properties.jobtitle', targetField: 'title', required: false },\n  { sourceField: 'properties.phone', targetField: 'phone', required: false },\n  { sourceField: 'properties.company', targetField: 'organization_name', required: false },\n  { sourceField: 'properties.website', targetField: 'organization_domain', transform: extractDomain, required: false },\n];\n\nfunction transformRecord(record: any, mappings: FieldMapping[]): any {\n  const transformed: any = {};\n  const errors: string[] = [];\n\n  for (const mapping of mappings) {\n    const value = getNestedValue(record, mapping.sourceField);\n\n    if (mapping.required && !value) {\n      errors.push(`Missing required field: ${mapping.sourceField}`);\n      continue;\n    }\n\n    if (value) {\n      let transformedValue = mapping.transform ? mapping.transform(value) : value;\n\n      if (mapping.validation && !mapping.validation(transformedValue)) {\n        errors.push(`Invalid value for ${mapping.sourceField}: ${value}`);\n        continue;\n      }\n\n      transformed[mapping.targetField] = transformedValue;\n    }\n  }\n\n  return { data: transformed, errors };\n}\n```\n\n## Migration Execution\n\n### Phased Migration Strategy\n\n```typescript\n\u002F\u002F src\u002Fmigration\u002Fphased-migration.ts\ninterface MigrationPhase {\n  name: string;\n  percentage: number;\n  criteria: any;\n  validation: () => Promise\u003Cboolean>;\n  rollbackPlan: () => Promise\u003Cvoid>;\n}\n\nconst MIGRATION_PHASES: MigrationPhase[] = [\n  {\n    name: 'Pilot',\n    percentage: 1,\n    criteria: { createdAt: { gt: '2024-01-01' }, hasEmail: true },\n    validation: async () => {\n      const migrated = await getMigratedCount('pilot');\n      const errors = await getErrorCount('pilot');\n      return errors \u002F migrated \u003C 0.01; \u002F\u002F Less than 1% error rate\n    },\n    rollbackPlan: async () => {\n      await deleteApolloContacts({ tag: 'migration-pilot' });\n    },\n  },\n  {\n    name: 'Early Adopters',\n    percentage: 10,\n    criteria: { hasEmail: true, engagementScore: { gt: 50 } },\n    validation: async () => {\n      \u002F\u002F Validate data integrity\n      const sample = await sampleMigratedRecords(100);\n      const integrity = await validateDataIntegrity(sample);\n      return integrity.score > 0.95;\n    },\n    rollbackPlan: async () => {\n      await deleteApolloContacts({ tag: 'migration-early' });\n    },\n  },\n  {\n    name: 'Main Migration',\n    percentage: 75,\n    criteria: { hasEmail: true },\n    validation: async () => {\n      \u002F\u002F Full validation suite\n      return await runFullValidation();\n    },\n    rollbackPlan: async () => {\n      \u002F\u002F This is risky - need careful planning\n      console.warn('Full rollback required - contact support');\n    },\n  },\n  {\n    name: 'Cleanup',\n    percentage: 14,\n    criteria: {}, \u002F\u002F Remaining records\n    validation: async () => true,\n    rollbackPlan: async () => {},\n  },\n];\n\nasync function executePhasedMigration(): Promise\u003Cvoid> {\n  for (const phase of MIGRATION_PHASES) {\n    console.log(`Starting phase: ${phase.name} (${phase.percentage}%)`);\n\n    \u002F\u002F Get records for this phase\n    const records = await getRecordsForPhase(phase);\n    console.log(`Found ${records.length} records for ${phase.name}`);\n\n    \u002F\u002F Migrate in batches\n    const batchSize = 100;\n    for (let i = 0; i \u003C records.length; i += batchSize) {\n      const batch = records.slice(i, i + batchSize);\n      await migrateBatch(batch, phase.name);\n\n      \u002F\u002F Progress update\n      console.log(`Progress: ${i + batch.length}\u002F${records.length}`);\n\n      \u002F\u002F Rate limit\n      await sleep(1000);\n    }\n\n    \u002F\u002F Validate phase\n    const isValid = await phase.validation();\n    if (!isValid) {\n      console.error(`Phase ${phase.name} validation failed!`);\n      await phase.rollbackPlan();\n      throw new Error(`Migration failed at phase: ${phase.name}`);\n    }\n\n    console.log(`Phase ${phase.name} completed successfully`);\n  }\n}\n```\n\n### Batch Migration Worker\n\n```typescript\n\u002F\u002F src\u002Fmigration\u002Fbatch-worker.ts\nimport { Queue, Worker, Job } from 'bullmq';\n\ninterface MigrationJob {\n  records: any[];\n  phase: string;\n  batchNumber: number;\n}\n\nconst migrationQueue = new Queue('apollo-migration');\n\n\u002F\u002F Producer\nasync function enqueueMigrationBatch(\n  records: any[],\n  phase: string,\n  batchNumber: number\n): Promise\u003Cvoid> {\n  await migrationQueue.add('migrate', {\n    records,\n    phase,\n    batchNumber,\n  }, {\n    attempts: 3,\n    backoff: {\n      type: 'exponential',\n      delay: 5000,\n    },\n    removeOnComplete: 100,\n    removeOnFail: false,\n  });\n}\n\n\u002F\u002F Consumer\nconst worker = new Worker('apollo-migration', async (job: Job\u003CMigrationJob>) => {\n  const { records, phase, batchNumber } = job.data;\n\n  const results = {\n    success: 0,\n    failed: 0,\n    errors: [] as any[],\n  };\n\n  for (const record of records) {\n    try {\n      \u002F\u002F Transform record\n      const transformed = transformRecord(record, getMapping(record.source));\n\n      if (transformed.errors.length > 0) {\n        results.failed++;\n        results.errors.push({ record, errors: transformed.errors });\n        continue;\n      }\n\n      \u002F\u002F Create in Apollo\n      await apollo.createContact(transformed.data);\n\n      \u002F\u002F Store mapping for rollback\n      await storeMigrationMapping(record.id, transformed.data.id, phase);\n\n      results.success++;\n    } catch (error: any) {\n      results.failed++;\n      results.errors.push({ record, error: error.message });\n    }\n\n    \u002F\u002F Update job progress\n    await job.updateProgress((results.success + results.failed) \u002F records.length * 100);\n  }\n\n  \u002F\u002F Log results\n  console.log(`Batch ${batchNumber}: ${results.success} success, ${results.failed} failed`);\n\n  if (results.errors.length > 0) {\n    await storeFailedRecords(results.errors, phase, batchNumber);\n  }\n\n  return results;\n});\n```\n\n## Validation & Reconciliation\n\n```typescript\n\u002F\u002F src\u002Fmigration\u002Fvalidation.ts\ninterface ValidationResult {\n  totalSource: number;\n  totalTarget: number;\n  matched: number;\n  mismatched: number;\n  missing: number;\n  extra: number;\n  fieldDiscrepancies: FieldDiscrepancy[];\n}\n\ninterface FieldDiscrepancy {\n  recordId: string;\n  field: string;\n  sourceValue: any;\n  targetValue: any;\n}\n\nasync function validateMigration(): Promise\u003CValidationResult> {\n  \u002F\u002F Get all source records\n  const sourceRecords = await fetchAllSourceRecords();\n  const sourceMap = new Map(sourceRecords.map(r => [r.email, r]));\n\n  \u002F\u002F Get all migrated records from Apollo\n  const apolloRecords = await fetchAllApolloContacts();\n  const apolloMap = new Map(apolloRecords.map(r => [r.email, r]));\n\n  const result: ValidationResult = {\n    totalSource: sourceRecords.length,\n    totalTarget: apolloRecords.length,\n    matched: 0,\n    mismatched: 0,\n    missing: 0,\n    extra: 0,\n    fieldDiscrepancies: [],\n  };\n\n  \u002F\u002F Check source records exist in Apollo\n  for (const [email, sourceRecord] of sourceMap) {\n    const apolloRecord = apolloMap.get(email);\n\n    if (!apolloRecord) {\n      result.missing++;\n      continue;\n    }\n\n    \u002F\u002F Compare fields\n    const discrepancies = compareRecords(sourceRecord, apolloRecord);\n    if (discrepancies.length === 0) {\n      result.matched++;\n    } else {\n      result.mismatched++;\n      result.fieldDiscrepancies.push(...discrepancies);\n    }\n  }\n\n  \u002F\u002F Check for extra records in Apollo\n  for (const [email] of apolloMap) {\n    if (!sourceMap.has(email)) {\n      result.extra++;\n    }\n  }\n\n  return result;\n}\n\nfunction compareRecords(source: any, target: any): FieldDiscrepancy[] {\n  const discrepancies: FieldDiscrepancy[] = [];\n  const fieldsToCompare = ['first_name', 'last_name', 'title', 'phone'];\n\n  for (const field of fieldsToCompare) {\n    const sourceValue = normalizeValue(source[field]);\n    const targetValue = normalizeValue(target[field]);\n\n    if (sourceValue !== targetValue) {\n      discrepancies.push({\n        recordId: source.id,\n        field,\n        sourceValue,\n        targetValue,\n      });\n    }\n  }\n\n  return discrepancies;\n}\n```\n\n## Rollback Strategy\n\n```typescript\n\u002F\u002F src\u002Fmigration\u002Frollback.ts\ninterface RollbackPlan {\n  phase: string;\n  recordIds: string[];\n  timestamp: Date;\n}\n\nasync function createRollbackPlan(phase: string): Promise\u003CRollbackPlan> {\n  const mappings = await prisma.migrationMapping.findMany({\n    where: { phase },\n  });\n\n  return {\n    phase,\n    recordIds: mappings.map(m => m.apolloId),\n    timestamp: new Date(),\n  };\n}\n\nasync function executeRollback(plan: RollbackPlan): Promise\u003Cvoid> {\n  console.log(`Rolling back ${plan.recordIds.length} records from phase: ${plan.phase}`);\n\n  \u002F\u002F Delete from Apollo in batches\n  const batchSize = 50;\n  for (let i = 0; i \u003C plan.recordIds.length; i += batchSize) {\n    const batch = plan.recordIds.slice(i, i + batchSize);\n\n    await Promise.all(\n      batch.map(async (id) => {\n        try {\n          \u002F\u002F Apollo may not have delete API - mark as inactive instead\n          await apollo.updateContact(id, { status: 'inactive' });\n        } catch (error) {\n          console.error(`Failed to rollback contact ${id}:`, error);\n        }\n      })\n    );\n\n    console.log(`Rollback progress: ${i + batch.length}\u002F${plan.recordIds.length}`);\n    await sleep(1000);\n  }\n\n  \u002F\u002F Update migration mappings\n  await prisma.migrationMapping.updateMany({\n    where: { phase: plan.phase },\n    data: { rolledBack: true, rolledBackAt: new Date() },\n  });\n\n  console.log(`Rollback complete for phase: ${plan.phase}`);\n}\n```\n\n## Migration Dashboard\n\n```typescript\n\u002F\u002F src\u002Froutes\u002Fadmin\u002Fmigration.ts\nrouter.get('\u002Fmigration\u002Fstatus', async (req, res) => {\n  const status = {\n    phases: await getMigrationPhaseStatus(),\n    progress: await getOverallProgress(),\n    errors: await getRecentErrors(50),\n    queue: await getQueueStatus(),\n  };\n\n  res.json(status);\n});\n\nrouter.post('\u002Fmigration\u002Fpause', async (req, res) => {\n  await migrationQueue.pause();\n  res.json({ status: 'paused' });\n});\n\nrouter.post('\u002Fmigration\u002Fresume', async (req, res) => {\n  await migrationQueue.resume();\n  res.json({ status: 'resumed' });\n});\n\nrouter.post('\u002Fmigration\u002Frollback\u002F:phase', async (req, res) => {\n  const plan = await createRollbackPlan(req.params.phase);\n  await executeRollback(plan);\n  res.json({ status: 'rolled back', plan });\n});\n```\n\n## Output\n- Pre-migration assessment framework\n- Field mapping configurations\n- Phased migration strategy\n- Batch processing workers\n- Validation and reconciliation\n- Rollback procedures\n\n## Error Handling\n| Issue | Resolution |\n|-------|------------|\n| Field mapping error | Review and fix mapping |\n| Batch failure | Retry with smaller batch |\n| Validation mismatch | Investigate and re-migrate |\n| Rollback needed | Execute phase rollback |\n\n## Resources\n- [Apollo Import Documentation](https:\u002F\u002Fknowledge.apollo.io\u002Fhc\u002Fen-us\u002Farticles\u002F4415154183053)\n- [Salesforce Export Guide](https:\u002F\u002Fhelp.salesforce.com\u002Fs\u002FarticleView?id=sf.exporting_data.htm)\n- [HubSpot Export Guide](https:\u002F\u002Fknowledge.hubspot.com\u002Fcrm-setup\u002Fexport-contacts-companies-deals-or-tickets)\n\n## Completion\nThis completes the Apollo skill pack. All 24 skills are now available for Claude Code users integrating with Apollo.io.\n","# Apollo Migration Deep Dive\n\n## Overview\nComprehensive guide for migrating to Apollo.io from other CRMs and data sources, including data mapping, validation, and rollback strategies.\n\n## Migration Planning\n\n### Pre-Migration Assessment\n\n```typescript\n\u002F\u002F scripts\u002Fmigration-assessment.ts\ninterface MigrationAssessment {\n  source: {\n    system: string;\n    recordCount: number;\n    dataQuality: DataQualityReport;\n    fieldMapping: FieldMappingAnalysis;\n  };\n  target: {\n    apolloPlan: string;\n    creditBudget: number;\n    apiLimits: APILimits;\n  };\n  risk: {\n    level: 'low' | 'medium' | 'high';\n    factors: string[];\n    mitigations: string[];\n  };\n  timeline: {\n    estimatedDuration: string;\n    phases: Phase[];\n  };\n}\n\nasync function assessMigration(sourceConfig: any): Promise\u003CMigrationAssessment> {\n  \u002F\u002F Analyze source data\n  const sourceAnalysis = await analyzeSourceData(sourceConfig);\n\n  \u002F\u002F Check Apollo capacity\n  const apolloCapacity = await checkApolloCapacity();\n\n  \u002F\u002F Calculate risks\n  const risks = calculateRisks(sourceAnalysis, apolloCapacity);\n\n  \u002F\u002F Estimate timeline\n  const timeline = estimateTimeline(sourceAnalysis, apolloCapacity);\n\n  return {\n    source: sourceAnalysis,\n    target: apolloCapacity,\n    risk: risks,\n    timeline,\n  };\n}\n\nasync function analyzeSourceData(config: any): Promise\u003CSourceAnalysis> {\n  const records = await fetchSourceRecords(config);\n\n  return {\n    system: config.system,\n    recordCount: records.length,\n    dataQuality: {\n      emailValid: records.filter(r => isValidEmail(r.email)).length \u002F records.length,\n      emailPresent: records.filter(r => r.email).length \u002F records.length,\n      phonePresent: records.filter(r => r.phone).length \u002F records.length,\n      companyPresent: records.filter(r => r.company).length \u002F records.length,\n      duplicates: findDuplicates(records).length,\n    },\n    fieldMapping: analyzeFields(records),\n  };\n}\n```\n\n### Field Mapping\n\n```typescript\n\u002F\u002F src\u002Fmigration\u002Ffield-mapper.ts\ninterface FieldMapping {\n  sourceField: string;\n  targetField: string;\n  transform?: (value: any) => any;\n  required: boolean;\n  validation?: (value: any) => boolean;\n}\n\nconst SALESFORCE_TO_APOLLO: FieldMapping[] = [\n  {\n    sourceField: 'Email',\n    targetField: 'email',\n    required: true,\n    validation: isValidEmail,\n  },\n  {\n    sourceField: 'FirstName',\n    targetField: 'first_name',\n    required: false,\n  },\n  {\n    sourceField: 'LastName',\n    targetField: 'last_name',\n    required: false,\n  },\n  {\n    sourceField: 'Title',\n    targetField: 'title',\n    required: false,\n    transform: normalizeTitle,\n  },\n  {\n    sourceField: 'Phone',\n    targetField: 'phone',\n    required: false,\n    transform: normalizePhone,\n  },\n  {\n    sourceField: 'Account.Name',\n    targetField: 'organization_name',\n    required: false,\n  },\n  {\n    sourceField: 'Account.Website',\n    targetField: 'organization_domain',\n    transform: extractDomain,\n    required: false,\n  },\n  {\n    sourceField: 'LinkedIn_URL__c',\n    targetField: 'linkedin_url',\n    required: false,\n    validation: isValidLinkedInUrl,\n  },\n];\n\nconst HUBSPOT_TO_APOLLO: FieldMapping[] = [\n  { sourceField: 'properties.email', targetField: 'email', required: true },\n  { sourceField: 'properties.firstname', targetField: 'first_name', required: false },\n  { sourceField: 'properties.lastname', targetField: 'last_name', required: false },\n  { sourceField: 'properties.jobtitle', targetField: 'title', required: false },\n  { sourceField: 'properties.phone', targetField: 'phone', required: false },\n  { sourceField: 'properties.company', targetField: 'organization_name', required: false },\n  { sourceField: 'properties.website', targetField: 'organization_domain', transform: extractDomain, required: false },\n];\n\nfunction transformRecord(record: any, mappings: FieldMapping[]): any {\n  const transformed: any = {};\n  const errors: string[] = [];\n\n  for (const mapping of mappings) {\n    const value = getNestedValue(record, mapping.sourceField);\n\n    if (mapping.required && !value) {\n      errors.push(`Missing required field: ${mapping.sourceField}`);\n      continue;\n    }\n\n    if (value) {\n      let transformedValue = mapping.transform ? mapping.transform(value) : value;\n\n      if (mapping.validation && !mapping.validation(transformedValue)) {\n        errors.push(`Invalid value for ${mapping.sourceField}: ${value}`);\n        continue;\n      }\n\n      transformed[mapping.targetField] = transformedValue;\n    }\n  }\n\n  return { data: transformed, errors };\n}\n```\n\n## Migration Execution\n\n### Phased Migration Strategy\n\n```typescript\n\u002F\u002F src\u002Fmigration\u002Fphased-migration.ts\ninterface MigrationPhase {\n  name: string;\n  percentage: number;\n  criteria: any;\n  validation: () => Promise\u003Cboolean>;\n  rollbackPlan: () => Promise\u003Cvoid>;\n}\n\nconst MIGRATION_PHASES: MigrationPhase[] = [\n  {\n    name: 'Pilot',\n    percentage: 1,\n    criteria: { createdAt: { gt: '2024-01-01' }, hasEmail: true },\n    validation: async () => {\n      const migrated = await getMigratedCount('pilot');\n      const errors = await getErrorCount('pilot');\n      return errors \u002F migrated \u003C 0.01; \u002F\u002F Less than 1% error rate\n    },\n    rollbackPlan: async () => {\n      await deleteApolloContacts({ tag: 'migration-pilot' });\n    },\n  },\n  {\n    name: 'Early Adopters',\n    percentage: 10,\n    criteria: { hasEmail: true, engagementScore: { gt: 50 } },\n    validation: async () => {\n      \u002F\u002F Validate data integrity\n      const sample = await sampleMigratedRecords(100);\n      const integrity = await validateDataIntegrity(sample);\n      return integrity.score > 0.95;\n    },\n    rollbackPlan: async () => {\n      await deleteApolloContacts({ tag: 'migration-early' });\n    },\n  },\n  {\n    name: 'Main Migration',\n    percentage: 75,\n    criteria: { hasEmail: true },\n    validation: async () => {\n      \u002F\u002F Full validation suite\n      return await runFullValidation();\n    },\n    rollbackPlan: async () => {\n      \u002F\u002F This is risky - need careful planning\n      console.warn('Full rollback required - contact support');\n    },\n  },\n  {\n    name: 'Cleanup',\n    percentage: 14,\n    criteria: {}, \u002F\u002F Remaining records\n    validation: async () => true,\n    rollbackPlan: async () => {},\n  },\n];\n\nasync function executePhasedMigration(): Promise\u003Cvoid> {\n  for (const phase of MIGRATION_PHASES) {\n    console.log(`Starting phase: ${phase.name} (${phase.percentage}%)`);\n\n    \u002F\u002F Get records for this phase\n    const records = await getRecordsForPhase(phase);\n    console.log(`Found ${records.length} records for ${phase.name}`);\n\n    \u002F\u002F Migrate in batches\n    const batchSize = 100;\n    for (let i = 0; i \u003C records.length; i += batchSize) {\n      const batch = records.slice(i, i + batchSize);\n      await migrateBatch(batch, phase.name);\n\n      \u002F\u002F Progress update\n      console.log(`Progress: ${i + batch.length}\u002F${records.length}`);\n\n      \u002F\u002F Rate limit\n      await sleep(1000);\n    }\n\n    \u002F\u002F Validate phase\n    const isValid = await phase.validation();\n    if (!isValid) {\n      console.error(`Phase ${phase.name} validation failed!`);\n      await phase.rollbackPlan();\n      throw new Error(`Migration failed at phase: ${phase.name}`);\n    }\n\n    console.log(`Phase ${phase.name} completed successfully`);\n  }\n}\n```\n\n### Batch Migration Worker\n\n```typescript\n\u002F\u002F src\u002Fmigration\u002Fbatch-worker.ts\nimport { Queue, Worker, Job } from 'bullmq';\n\ninterface MigrationJob {\n  records: any[];\n  phase: string;\n  batchNumber: number;\n}\n\nconst migrationQueue = new Queue('apollo-migration');\n\n\u002F\u002F Producer\nasync function enqueueMigrationBatch(\n  records: any[],\n  phase: string,\n  batchNumber: number\n): Promise\u003Cvoid> {\n  await migrationQueue.add('migrate', {\n    records,\n    phase,\n    batchNumber,\n  }, {\n    attempts: 3,\n    backoff: {\n      type: 'exponential',\n      delay: 5000,\n    },\n    removeOnComplete: 100,\n    removeOnFail: false,\n  });\n}\n\n\u002F\u002F Consumer\nconst worker = new Worker('apollo-migration', async (job: Job\u003CMigrationJob>) => {\n  const { records, phase, batchNumber } = job.data;\n\n  const results = {\n    success: 0,\n    failed: 0,\n    errors: [] as any[],\n  };\n\n  for (const record of records) {\n    try {\n      \u002F\u002F Transform record\n      const transformed = transformRecord(record, getMapping(record.source));\n\n      if (transformed.errors.length > 0) {\n        results.failed++;\n        results.errors.push({ record, errors: transformed.errors });\n        continue;\n      }\n\n      \u002F\u002F Create in Apollo\n      await apollo.createContact(transformed.data);\n\n      \u002F\u002F Store mapping for rollback\n      await storeMigrationMapping(record.id, transformed.data.id, phase);\n\n      results.success++;\n    } catch (error: any) {\n      results.failed++;\n      results.errors.push({ record, error: error.message });\n    }\n\n    \u002F\u002F Update job progress\n    await job.updateProgress((results.success + results.failed) \u002F records.length * 100);\n  }\n\n  \u002F\u002F Log results\n  console.log(`Batch ${batchNumber}: ${results.success} success, ${results.failed} failed`);\n\n  if (results.errors.length > 0) {\n    await storeFailedRecords(results.errors, phase, batchNumber);\n  }\n\n  return results;\n});\n```\n\n## Validation & Reconciliation\n\n```typescript\n\u002F\u002F src\u002Fmigration\u002Fvalidation.ts\ninterface ValidationResult {\n  totalSource: number;\n  totalTarget: number;\n  matched: number;\n  mismatched: number;\n  missing: number;\n  extra: number;\n  fieldDiscrepancies: FieldDiscrepancy[];\n}\n\ninterface FieldDiscrepancy {\n  recordId: string;\n  field: string;\n  sourceValue: any;\n  targetValue: any;\n}\n\nasync function validateMigration(): Promise\u003CValidationResult> {\n  \u002F\u002F Get all source records\n  const sourceRecords = await fetchAllSourceRecords();\n  const sourceMap = new Map(sourceRecords.map(r => [r.email, r]));\n\n  \u002F\u002F Get all migrated records from Apollo\n  const apolloRecords = await fetchAllApolloContacts();\n  const apolloMap = new Map(apolloRecords.map(r => [r.email, r]));\n\n  const result: ValidationResult = {\n    totalSource: sourceRecords.length,\n    totalTarget: apolloRecords.length,\n    matched: 0,\n    mismatched: 0,\n    missing: 0,\n    extra: 0,\n    fieldDiscrepancies: [],\n  };\n\n  \u002F\u002F Check source records exist in Apollo\n  for (const [email, sourceRecord] of sourceMap) {\n    const apolloRecord = apolloMap.get(email);\n\n    if (!apolloRecord) {\n      result.missing++;\n      continue;\n    }\n\n    \u002F\u002F Compare fields\n    const discrepancies = compareRecords(sourceRecord, apolloRecord);\n    if (discrepancies.length === 0) {\n      result.matched++;\n    } else {\n      result.mismatched++;\n      result.fieldDiscrepancies.push(...discrepancies);\n    }\n  }\n\n  \u002F\u002F Check for extra records in Apollo\n  for (const [email] of apolloMap) {\n    if (!sourceMap.has(email)) {\n      result.extra++;\n    }\n  }\n\n  return result;\n}\n\nfunction compareRecords(source: any, target: any): FieldDiscrepancy[] {\n  const discrepancies: FieldDiscrepancy[] = [];\n  const fieldsToCompare = ['first_name', 'last_name', 'title', 'phone'];\n\n  for (const field of fieldsToCompare) {\n    const sourceValue = normalizeValue(source[field]);\n    const targetValue = normalizeValue(target[field]);\n\n    if (sourceValue !== targetValue) {\n      discrepancies.push({\n        recordId: source.id,\n        field,\n        sourceValue,\n        targetValue,\n      });\n    }\n  }\n\n  return discrepancies;\n}\n```\n\n## Rollback Strategy\n\n```typescript\n\u002F\u002F src\u002Fmigration\u002Frollback.ts\ninterface RollbackPlan {\n  phase: string;\n  recordIds: string[];\n  timestamp: Date;\n}\n\nasync function createRollbackPlan(phase: string): Promise\u003CRollbackPlan> {\n  const mappings = await prisma.migrationMapping.findMany({\n    where: { phase },\n  });\n\n  return {\n    phase,\n    recordIds: mappings.map(m => m.apolloId),\n    timestamp: new Date(),\n  };\n}\n\nasync function executeRollback(plan: RollbackPlan): Promise\u003Cvoid> {\n  console.log(`Rolling back ${plan.recordIds.length} records from phase: ${plan.phase}`);\n\n  \u002F\u002F Delete from Apollo in batches\n  const batchSize = 50;\n  for (let i = 0; i \u003C plan.recordIds.length; i += batchSize) {\n    const batch = plan.recordIds.slice(i, i + batchSize);\n\n    await Promise.all(\n      batch.map(async (id) => {\n        try {\n          \u002F\u002F Apollo may not have delete API - mark as inactive instead\n          await apollo.updateContact(id, { status: 'inactive' });\n        } catch (error) {\n          console.error(`Failed to rollback contact ${id}:`, error);\n        }\n      })\n    );\n\n    console.log(`Rollback progress: ${i + batch.length}\u002F${plan.recordIds.length}`);\n    await sleep(1000);\n  }\n\n  \u002F\u002F Update migration mappings\n  await prisma.migrationMapping.updateMany({\n    where: { phase: plan.phase },\n    data: { rolledBack: true, rolledBackAt: new Date() },\n  });\n\n  console.log(`Rollback complete for phase: ${plan.phase}`);\n}\n```\n\n## Migration Dashboard\n\n```typescript\n\u002F\u002F src\u002Froutes\u002Fadmin\u002Fmigration.ts\nrouter.get('\u002Fmigration\u002Fstatus', async (req, res) => {\n  const status = {\n    phases: await getMigrationPhaseStatus(),\n    progress: await getOverallProgress(),\n    errors: await getRecentErrors(50),\n    queue: await getQueueStatus(),\n  };\n\n  res.json(status);\n});\n\nrouter.post('\u002Fmigration\u002Fpause', async (req, res) => {\n  await migrationQueue.pause();\n  res.json({ status: 'paused' });\n});\n\nrouter.post('\u002Fmigration\u002Fresume', async (req, res) => {\n  await migrationQueue.resume();\n  res.json({ status: 'resumed' });\n});\n\nrouter.post('\u002Fmigration\u002Frollback\u002F:phase', async (req, res) => {\n  const plan = await createRollbackPlan(req.params.phase);\n  await executeRollback(plan);\n  res.json({ status: 'rolled back', plan });\n});\n```\n\n## Output\n- Pre-migration assessment framework\n- Field mapping configurations\n- Phased migration strategy\n- Batch processing workers\n- Validation and reconciliation\n- Rollback procedures\n\n## Error Handling\n| Issue | Resolution |\n|-------|------------|\n| Field mapping error | Review and fix mapping |\n| Batch failure | Retry with smaller batch |\n| Validation mismatch | Investigate and re-migrate |\n| Rollback needed | Execute phase rollback |\n\n## Resources\n- [Apollo Import Documentation](https:\u002F\u002Fknowledge.apollo.io\u002Fhc\u002Fen-us\u002Farticles\u002F4415154183053)\n- [Salesforce Export Guide](https:\u002F\u002Fhelp.salesforce.com\u002Fs\u002FarticleView?id=sf.exporting_data.htm)\n- [HubSpot Export Guide](https:\u002F\u002Fknowledge.hubspot.com\u002Fcrm-setup\u002Fexport-contacts-companies-deals-or-tickets)\n\n## Completion\nThis completes the Apollo skill pack. All 24 skills are now available for Claude Code users integrating with Apollo.io.\n",{"name":5,"author":48,"license":15,"version":49,"description":50,"allowed-tools":51},"Jeremy Longshore \u003Cjeremy@intentsolutions.io>","1.0.0","Comprehensive Apollo.io migration strategies.\nUse when migrating from other CRMs to Apollo, consolidating data sources,\nor executing large-scale data migrations.\nTrigger with phrases like \"apollo migration\", \"migrate to apollo\",\n\"apollo data import\", \"crm to apollo\", \"apollo migration strategy\".\n","Read, Write, Edit, Bash(kubectl:*), Bash(curl:*)","main","7439377908fdee98c9bb5863391212b95453de95","tests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fapollo-pack\u002Fskills\u002Fapollo-migration-deep-dive",231,"https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust","https:\u002F\u002Fgithub.com\u002FDicklesworthstone","https:\u002F\u002Fwww.jeffreyemanuel.com\u002F","Building in NY","2026-11-12 03:15:57",{"source":8,"skillName":5,"commands":62,"prompt":72,"zipAvailable":73},[63,66,69],{"tool":64,"command":65},"npx","npx skills add Dicklesworthstone\u002Fpi_agent_rust --skill apollo-migration-deep-dive",{"tool":67,"command":68},"bunx","bunx skills add Dicklesworthstone\u002Fpi_agent_rust --skill apollo-migration-deep-dive",{"tool":70,"command":71},"pnpm","pnpm dlx skills add Dicklesworthstone\u002Fpi_agent_rust --skill apollo-migration-deep-dive","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fapollo-pack\u002Fskills\u002Fapollo-migration-deep-dive\u002FSKILL.md",true,[],[76,116,141,166,193,215],{"skillNo":77,"name":78,"nameZh":6,"description":79,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":80,"licenseFileUrl":81,"sourceHtmlUrl":82,"categories":83,"keywords":89,"publishedAt":43},"01M6FEGPPK0ZTKCCM0R3E3KS33","web-artifacts-builder","Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn\u002Fui). Use for complex artifacts requiring state management, routing, or shadcn\u002Fui components - not for simple single-file HTML\u002FJSX artifacts.","Apache-2.0","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Futilities\u002Fweb-artifacts-builder\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Futilities\u002Fweb-artifacts-builder\u002FSKILL.md",[84],{"categoryNo":85,"categoryName":86,"taxonomyType":87,"taxonomyTypeDesc":88},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",[90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,34,108,109,110,111,112,113,114,115],"web artifacts builder","web","artifacts","artifacts builder","builder","frontend","css","components","react","component","routing","state management","state","shadcn","file","ui","Tools","Tailwind","html","single-file","simple","ui components","multi","for","jsx","suite",{"skillNo":117,"name":118,"nameZh":6,"description":119,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":80,"licenseFileUrl":120,"sourceHtmlUrl":121,"categories":122,"keywords":127,"publishedAt":43},"01M6FEE9VTK1W4GY21AKREJXRG","webapp-testing","Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fsecurity\u002Fwebapp-testing\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fsecurity\u002Fwebapp-testing\u002FSKILL.md",[123,126],{"categoryNo":124,"categoryName":125,"taxonomyType":87,"taxonomyTypeDesc":88},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":85,"categoryName":86,"taxonomyType":87,"taxonomyTypeDesc":88},[128,129,130,95,131,132,91,133,134,135,105,136,137,138,139,140,113],"testing","webapp testing","webapp","screenshots","playwright","debugging","toolkit","browser","logs","applications","behavior","local","with",{"skillNo":142,"name":143,"nameZh":6,"description":144,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":145,"sourceHtmlUrl":146,"categories":147,"keywords":148,"publishedAt":43},"01M6FE20F7ZTQBFWKF4MPJ2SBX","neuropixels-analysis","Neuropixels neural recording analysis. Load SpikeGLX\u002FOpenEphys data, preprocess, motion correction, Kilosort4 spike sorting, quality metrics, Allen\u002FIBL curation, AI-assisted visual analysis, for Neuropixels 1.0\u002F2.0 extracellular electrophysiology. Use when working with neural recordings, spike sorting, extracellular electrophysiology, or when the user mentions Neuropixels, SpikeGLX, Open Ephys, Kilosort, quality metrics, or unit curation.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fneuropixels-analysis\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fneuropixels-analysis\u002FSKILL.md",[],[149,150,151,152,25,153,154,155,34,156,157,158,159,160,161,162,140,163,164,165,113,24],"analysis","neuropixels analysis","spike","metrics","open","quality","user","recordings","Neural","motion","visual","quality metrics","unit","sorting","curation","recording","load",{"skillNo":167,"name":168,"nameZh":6,"description":169,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":80,"licenseFileUrl":170,"sourceHtmlUrl":171,"categories":172,"keywords":176,"publishedAt":43},"01M6FDP0PDK6F1GGX395C7625Z","skill-creator","Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fskill-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fskill-creator\u002FSKILL.md",[173],{"categoryNo":174,"categoryName":175,"taxonomyType":87,"taxonomyTypeDesc":88},"01JBSEEDCAT000000000000023","Skill与智能体开发",[177,178,179,180,181,182,183,184,185,186,187,188,189,190,140,113,191,24,192],"skill creator","creator","workflows","create","update","capabilities","knowledge","tool","integrations","specialized","guide","new skill","existing skill","users","Existing","new",{"skillNo":194,"name":195,"nameZh":6,"description":196,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":197,"sourceHtmlUrl":198,"categories":199,"keywords":201,"publishedAt":43},"01M6FDM8Y7VK7NYG9SM7QPA3PW","notebooklm","Use this skill to query your Google NotebookLM notebooks directly from Claude Code for source-grounded, citation-backed answers from Gemini. Browser automation, library management, persistent auth. Drastically reduced hallucinations through document-only responses.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fnotebooklm\u002FLICENSE","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fnotebooklm\u002FSKILL.md",[200],{"categoryNo":174,"categoryName":175,"taxonomyType":87,"taxonomyTypeDesc":88},[195,202,203,204,205,206,207,135,208,209,34,210,211,212,213,113,214],"google","browser automation","gemini","automation","auth","code","library","management","only","document","query","Citation","source",{"skillNo":216,"name":217,"nameZh":6,"description":218,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":80,"licenseFileUrl":219,"sourceHtmlUrl":220,"categories":221,"keywords":228,"publishedAt":43},"01M6FDHPXE10J3XGTCH5HBHS1M","slack-gif-creator","Knowledge and utilities for creating animated GIFs optimized for Slack. Provides constraints, validation tools, and animation concepts. Use when users request animated GIFs for Slack like \"make me a GIF of X doing Y for Slack.\"","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fenterprise-communication\u002Fslack-gif-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fenterprise-communication\u002Fslack-gif-creator\u002FSKILL.md",[222,225],{"categoryNo":223,"categoryName":224,"taxonomyType":87,"taxonomyTypeDesc":88},"01JBSEEDCAT000000000000005","邮件与沟通",{"categoryNo":226,"categoryName":227,"taxonomyType":87,"taxonomyTypeDesc":88},"01JBSEEDCAT000000000000016","图像与多媒体",[229,230,231,178,232,106,233,234,183,34,235,190,236,237,238,113,239,24],"slack gif creator","slack","gif","validation","constraints","Animation","me","make","Utilities","concepts","request"]