[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6F7ES0259G7DVDFKA2NKE3D":3,"skill-same:01M6F7ES0259G7DVDFKA2NKE3D":82},{"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":59,"commitSha":60,"skillDirectory":61,"forksCount":62,"repositoryHtmlUrl":63,"repositoryHomepageUrl":64,"ownerHtmlUrl":65,"ownerBlogUrl":6,"ownerDescription":66,"updatedAt":67,"install":68,"resources":81},"01M6F7ES0259G7DVDFKA2NKE3D","assemblyai-local-dev-loop",null,"Configure AssemblyAI local development with hot reload and testing.\nUse when setting up a development environment, configuring test workflows,\nor establishing a fast iteration cycle with AssemblyAI.\nTrigger with phrases like \"assemblyai dev setup\", \"assemblyai local development\",\n\"assemblyai dev environment\", \"develop with assemblyai\".","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\u002Fassemblyai-local-dev-loop\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"local dev","assemblyai local dev loop","assemblyai","local","loop","dev","Bash","code","configure","text","read","write","edit","up","cycle","workflows","iteration","io","dev setup","testing","2026-11-10 10:12:30",false,"---\nname: assemblyai-local-dev-loop\ndescription: |\n  Configure AssemblyAI local development with hot reload and testing.\n  Use when setting up a development environment, configuring test workflows,\n  or establishing a fast iteration cycle with AssemblyAI.\n  Trigger with phrases like \"assemblyai dev setup\", \"assemblyai local development\",\n  \"assemblyai dev environment\", \"develop with assemblyai\".\nallowed-tools: Read, Write, Edit, Bash(npm:*), Bash(pnpm:*), Grep\nversion: 1.0.0\nlicense: MIT\nauthor: Jeremy Longshore \u003Cjeremy@intentsolutions.io>\ntags: [saas, ai, speech-to-text, assemblyai, transcription]\ncompatible-with: claude-code\n---\n\n# AssemblyAI Local Dev Loop\n\n## Overview\nSet up a fast, reproducible local development workflow for AssemblyAI transcription and LeMUR projects with mocking, caching, and hot reload.\n\n## Prerequisites\n- Completed `assemblyai-install-auth` setup\n- Node.js 18+ with npm\u002Fpnpm\n- TypeScript project with `tsx` or `ts-node`\n\n## Instructions\n\n### Step 1: Project Structure\n\n```\nmy-assemblyai-project\u002F\n├── src\u002F\n│   ├── assemblyai\u002F\n│   │   ├── client.ts       # Singleton client\n│   │   ├── transcribe.ts   # Transcription helpers\n│   │   └── lemur.ts        # LeMUR helpers\n│   └── index.ts\n├── tests\u002F\n│   ├── transcribe.test.ts\n│   └── fixtures\u002F\n│       └── sample-transcript.json  # Cached API response\n├── .env.local              # Local secrets (git-ignored)\n├── .env.example            # Template for team\n└── package.json\n```\n\n### Step 2: Dev Scripts\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"tsx watch src\u002Findex.ts\",\n    \"test\": \"vitest\",\n    \"test:watch\": \"vitest --watch\",\n    \"transcribe\": \"tsx src\u002Fassemblyai\u002Ftranscribe.ts\"\n  },\n  \"devDependencies\": {\n    \"tsx\": \"^4.7.0\",\n    \"vitest\": \"^1.6.0\",\n    \"dotenv\": \"^16.4.0\"\n  },\n  \"dependencies\": {\n    \"assemblyai\": \"^4.8.0\"\n  }\n}\n```\n\n### Step 3: Singleton Client with Env Loading\n\n```typescript\n\u002F\u002F src\u002Fassemblyai\u002Fclient.ts\nimport 'dotenv\u002Fconfig';\nimport { AssemblyAI } from 'assemblyai';\n\nlet instance: AssemblyAI | null = null;\n\nexport function getClient(): AssemblyAI {\n  if (!instance) {\n    if (!process.env.ASSEMBLYAI_API_KEY) {\n      throw new Error('ASSEMBLYAI_API_KEY not set. Copy .env.example to .env.local');\n    }\n    instance = new AssemblyAI({\n      apiKey: process.env.ASSEMBLYAI_API_KEY,\n    });\n  }\n  return instance;\n}\n```\n\n### Step 4: Cache Transcription Results for Fast Iteration\n\n```typescript\n\u002F\u002F src\u002Fassemblyai\u002Ftranscribe.ts\nimport fs from 'fs';\nimport path from 'path';\nimport { getClient } from '.\u002Fclient';\nimport type { Transcript } from 'assemblyai';\n\nconst CACHE_DIR = path.join(process.cwd(), '.assemblyai-cache');\n\nexport async function transcribeWithCache(\n  audioUrl: string,\n  options: Record\u003Cstring, any> = {}\n): Promise\u003CTranscript> {\n  const cacheKey = Buffer.from(audioUrl + JSON.stringify(options))\n    .toString('base64url')\n    .slice(0, 32);\n  const cachePath = path.join(CACHE_DIR, `${cacheKey}.json`);\n\n  \u002F\u002F Return cached result in dev\n  if (process.env.NODE_ENV !== 'production' && fs.existsSync(cachePath)) {\n    console.log('[dev] Using cached transcript:', cacheKey);\n    return JSON.parse(fs.readFileSync(cachePath, 'utf-8'));\n  }\n\n  const client = getClient();\n  const transcript = await client.transcripts.transcribe({\n    audio: audioUrl,\n    ...options,\n  });\n\n  \u002F\u002F Cache for next run\n  fs.mkdirSync(CACHE_DIR, { recursive: true });\n  fs.writeFileSync(cachePath, JSON.stringify(transcript, null, 2));\n  console.log('[dev] Cached transcript:', cacheKey);\n\n  return transcript;\n}\n```\n\n### Step 5: Test with Mocked Responses\n\n```typescript\n\u002F\u002F tests\u002Ftranscribe.test.ts\nimport { describe, it, expect, vi, beforeEach } from 'vitest';\nimport { AssemblyAI } from 'assemblyai';\n\n\u002F\u002F Mock the assemblyai module\nvi.mock('assemblyai', () => ({\n  AssemblyAI: vi.fn().mockImplementation(() => ({\n    transcripts: {\n      transcribe: vi.fn().mockResolvedValue({\n        id: 'test-transcript-id',\n        status: 'completed',\n        text: 'This is a test transcript.',\n        audio_duration: 30,\n        words: [\n          { text: 'This', start: 0, end: 200, confidence: 0.99 },\n          { text: 'is', start: 210, end: 350, confidence: 0.98 },\n        ],\n      }),\n      get: vi.fn(),\n      list: vi.fn(),\n    },\n    lemur: {\n      task: vi.fn().mockResolvedValue({\n        request_id: 'test-lemur-id',\n        response: 'Test summary of the audio.',\n      }),\n    },\n  })),\n}));\n\ndescribe('Transcription', () => {\n  it('should transcribe audio and return text', async () => {\n    const client = new AssemblyAI({ apiKey: 'test-key' });\n    const result = await client.transcripts.transcribe({\n      audio: 'https:\u002F\u002Fexample.com\u002Faudio.wav',\n    });\n\n    expect(result.status).toBe('completed');\n    expect(result.text).toContain('test transcript');\n    expect(result.words).toHaveLength(2);\n  });\n\n  it('should run LeMUR task on transcript', async () => {\n    const client = new AssemblyAI({ apiKey: 'test-key' });\n    const { response } = await client.lemur.task({\n      transcript_ids: ['test-transcript-id'],\n      prompt: 'Summarize this.',\n    });\n\n    expect(response).toContain('summary');\n  });\n});\n```\n\n## Output\n- Hot-reloading dev server with `tsx watch`\n- Cached transcription results to avoid repeated API calls during dev\n- Mocked test suite that runs without API credentials\n- Environment variable management with `.env.local`\n\n## Error Handling\n| Error | Cause | Solution |\n|-------|-------|----------|\n| `ASSEMBLYAI_API_KEY not set` | Missing env file | Copy `.env.example` to `.env.local` |\n| `Module not found: assemblyai` | Missing dependency | Run `npm install assemblyai` |\n| Stale cache results | Outdated cache | Delete `.assemblyai-cache\u002F` directory |\n| Test timeout | Slow mock setup | Ensure mocks resolve synchronously |\n\n## Resources\n- [AssemblyAI Node SDK](https:\u002F\u002Fgithub.com\u002FAssemblyAI\u002Fassemblyai-node-sdk)\n- [Vitest Documentation](https:\u002F\u002Fvitest.dev\u002F)\n- [tsx Documentation](https:\u002F\u002Fgithub.com\u002Fprivatenumber\u002Ftsx)\n\n## Next Steps\nSee `assemblyai-sdk-patterns` for production-ready code patterns.\n\n","# AssemblyAI Local Dev Loop\n\n## Overview\nSet up a fast, reproducible local development workflow for AssemblyAI transcription and LeMUR projects with mocking, caching, and hot reload.\n\n## Prerequisites\n- Completed `assemblyai-install-auth` setup\n- Node.js 18+ with npm\u002Fpnpm\n- TypeScript project with `tsx` or `ts-node`\n\n## Instructions\n\n### Step 1: Project Structure\n\n```\nmy-assemblyai-project\u002F\n├── src\u002F\n│   ├── assemblyai\u002F\n│   │   ├── client.ts       # Singleton client\n│   │   ├── transcribe.ts   # Transcription helpers\n│   │   └── lemur.ts        # LeMUR helpers\n│   └── index.ts\n├── tests\u002F\n│   ├── transcribe.test.ts\n│   └── fixtures\u002F\n│       └── sample-transcript.json  # Cached API response\n├── .env.local              # Local secrets (git-ignored)\n├── .env.example            # Template for team\n└── package.json\n```\n\n### Step 2: Dev Scripts\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"tsx watch src\u002Findex.ts\",\n    \"test\": \"vitest\",\n    \"test:watch\": \"vitest --watch\",\n    \"transcribe\": \"tsx src\u002Fassemblyai\u002Ftranscribe.ts\"\n  },\n  \"devDependencies\": {\n    \"tsx\": \"^4.7.0\",\n    \"vitest\": \"^1.6.0\",\n    \"dotenv\": \"^16.4.0\"\n  },\n  \"dependencies\": {\n    \"assemblyai\": \"^4.8.0\"\n  }\n}\n```\n\n### Step 3: Singleton Client with Env Loading\n\n```typescript\n\u002F\u002F src\u002Fassemblyai\u002Fclient.ts\nimport 'dotenv\u002Fconfig';\nimport { AssemblyAI } from 'assemblyai';\n\nlet instance: AssemblyAI | null = null;\n\nexport function getClient(): AssemblyAI {\n  if (!instance) {\n    if (!process.env.ASSEMBLYAI_API_KEY) {\n      throw new Error('ASSEMBLYAI_API_KEY not set. Copy .env.example to .env.local');\n    }\n    instance = new AssemblyAI({\n      apiKey: process.env.ASSEMBLYAI_API_KEY,\n    });\n  }\n  return instance;\n}\n```\n\n### Step 4: Cache Transcription Results for Fast Iteration\n\n```typescript\n\u002F\u002F src\u002Fassemblyai\u002Ftranscribe.ts\nimport fs from 'fs';\nimport path from 'path';\nimport { getClient } from '.\u002Fclient';\nimport type { Transcript } from 'assemblyai';\n\nconst CACHE_DIR = path.join(process.cwd(), '.assemblyai-cache');\n\nexport async function transcribeWithCache(\n  audioUrl: string,\n  options: Record\u003Cstring, any> = {}\n): Promise\u003CTranscript> {\n  const cacheKey = Buffer.from(audioUrl + JSON.stringify(options))\n    .toString('base64url')\n    .slice(0, 32);\n  const cachePath = path.join(CACHE_DIR, `${cacheKey}.json`);\n\n  \u002F\u002F Return cached result in dev\n  if (process.env.NODE_ENV !== 'production' && fs.existsSync(cachePath)) {\n    console.log('[dev] Using cached transcript:', cacheKey);\n    return JSON.parse(fs.readFileSync(cachePath, 'utf-8'));\n  }\n\n  const client = getClient();\n  const transcript = await client.transcripts.transcribe({\n    audio: audioUrl,\n    ...options,\n  });\n\n  \u002F\u002F Cache for next run\n  fs.mkdirSync(CACHE_DIR, { recursive: true });\n  fs.writeFileSync(cachePath, JSON.stringify(transcript, null, 2));\n  console.log('[dev] Cached transcript:', cacheKey);\n\n  return transcript;\n}\n```\n\n### Step 5: Test with Mocked Responses\n\n```typescript\n\u002F\u002F tests\u002Ftranscribe.test.ts\nimport { describe, it, expect, vi, beforeEach } from 'vitest';\nimport { AssemblyAI } from 'assemblyai';\n\n\u002F\u002F Mock the assemblyai module\nvi.mock('assemblyai', () => ({\n  AssemblyAI: vi.fn().mockImplementation(() => ({\n    transcripts: {\n      transcribe: vi.fn().mockResolvedValue({\n        id: 'test-transcript-id',\n        status: 'completed',\n        text: 'This is a test transcript.',\n        audio_duration: 30,\n        words: [\n          { text: 'This', start: 0, end: 200, confidence: 0.99 },\n          { text: 'is', start: 210, end: 350, confidence: 0.98 },\n        ],\n      }),\n      get: vi.fn(),\n      list: vi.fn(),\n    },\n    lemur: {\n      task: vi.fn().mockResolvedValue({\n        request_id: 'test-lemur-id',\n        response: 'Test summary of the audio.',\n      }),\n    },\n  })),\n}));\n\ndescribe('Transcription', () => {\n  it('should transcribe audio and return text', async () => {\n    const client = new AssemblyAI({ apiKey: 'test-key' });\n    const result = await client.transcripts.transcribe({\n      audio: 'https:\u002F\u002Fexample.com\u002Faudio.wav',\n    });\n\n    expect(result.status).toBe('completed');\n    expect(result.text).toContain('test transcript');\n    expect(result.words).toHaveLength(2);\n  });\n\n  it('should run LeMUR task on transcript', async () => {\n    const client = new AssemblyAI({ apiKey: 'test-key' });\n    const { response } = await client.lemur.task({\n      transcript_ids: ['test-transcript-id'],\n      prompt: 'Summarize this.',\n    });\n\n    expect(response).toContain('summary');\n  });\n});\n```\n\n## Output\n- Hot-reloading dev server with `tsx watch`\n- Cached transcription results to avoid repeated API calls during dev\n- Mocked test suite that runs without API credentials\n- Environment variable management with `.env.local`\n\n## Error Handling\n| Error | Cause | Solution |\n|-------|-------|----------|\n| `ASSEMBLYAI_API_KEY not set` | Missing env file | Copy `.env.example` to `.env.local` |\n| `Module not found: assemblyai` | Missing dependency | Run `npm install assemblyai` |\n| Stale cache results | Outdated cache | Delete `.assemblyai-cache\u002F` directory |\n| Test timeout | Slow mock setup | Ensure mocks resolve synchronously |\n\n## Resources\n- [AssemblyAI Node SDK](https:\u002F\u002Fgithub.com\u002FAssemblyAI\u002Fassemblyai-node-sdk)\n- [Vitest Documentation](https:\u002F\u002Fvitest.dev\u002F)\n- [tsx Documentation](https:\u002F\u002Fgithub.com\u002Fprivatenumber\u002Ftsx)\n\n## Next Steps\nSee `assemblyai-sdk-patterns` for production-ready code patterns.\n\n",{"name":5,"tags":49,"author":54,"license":15,"version":55,"description":56,"allowed-tools":57,"compatible-with":58},[50,51,52,26,53],"saas","ai","speech-to-text","transcription","Jeremy Longshore \u003Cjeremy@intentsolutions.io>","1.0.0","Configure AssemblyAI local development with hot reload and testing.\nUse when setting up a development environment, configuring test workflows,\nor establishing a fast iteration cycle with AssemblyAI.\nTrigger with phrases like \"assemblyai dev setup\", \"assemblyai local development\",\n\"assemblyai dev environment\", \"develop with assemblyai\".\n","Read, Write, Edit, Bash(npm:*), Bash(pnpm:*), Grep","claude-code","main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Fjeremylongshore\u002Fclaude-code-plugins-plus-skills\u002Fassemblyai-local-dev-loop",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":69,"prompt":79,"zipAvailable":80},[70,73,76],{"tool":71,"command":72},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill assemblyai-local-dev-loop",{"tool":74,"command":75},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill assemblyai-local-dev-loop",{"tool":77,"command":78},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill assemblyai-local-dev-loop","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fjeremylongshore\u002Fclaude-code-plugins-plus-skills\u002Fassemblyai-local-dev-loop\u002FSKILL.md",true,[],[83,95,105,114,120,127],{"skillNo":84,"name":85,"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":86,"categories":87,"keywords":91,"publishedAt":44},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[88],{"categoryNo":89,"categoryName":90,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[92,93,94],"model","model hierarchy","model hierarchy skill",{"skillNo":96,"name":97,"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":98,"categories":99,"keywords":101,"publishedAt":44},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[100],{"categoryNo":89,"categoryName":90,"taxonomyType":21,"taxonomyTypeDesc":22},[102,103,104],"MCP","zoom","zoom mcp",{"skillNo":106,"name":107,"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":108,"categories":109,"keywords":110,"publishedAt":44},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[111,112,113,103],"sdk","zoom apps sdk","apps",{"skillNo":115,"name":116,"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":117,"categories":118,"keywords":119,"publishedAt":44},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[116],{"skillNo":121,"name":122,"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":123,"categories":124,"keywords":126,"publishedAt":44},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[125],{"categoryNo":89,"categoryName":90,"taxonomyType":21,"taxonomyTypeDesc":22},[122],{"skillNo":128,"name":129,"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":130,"categories":131,"keywords":132,"publishedAt":44},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[129]]