[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M70FN73VGMX7VJ8PAG2VYJCC":3,"skill-same:01M70FN73VGMX7VJ8PAG2VYJCC":106},{"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":49,"commitSha":50,"skillDirectory":51,"forksCount":52,"repositoryHtmlUrl":53,"repositoryHomepageUrl":6,"ownerHtmlUrl":54,"ownerBlogUrl":55,"ownerDescription":56,"updatedAt":57,"install":58,"resources":71},"01M70FN73VGMX7VJ8PAG2VYJCC","SAI-podcast-download",null,"Atomic SAI skill. Download podcast episode audio from an RSS feed or a Spotify show URL (resolved to RSS via the iTunes Search API — Spotify itself blocks audio downloads). Resume-safe, retry-aware. Emits a manifest.json that downstream skills (local-transcribe, podcast-rag-index) consume. Use whenever you need to download a podcast, grab episodes of a show, pull audio for a Spotify show URL, or any workflow needs raw podcast MP3s as input.","lutzfinger\u002FSAI-baseversion","lutzfinger","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F2042951?v=4","01M70FMZRX9KAEB1JAP7GGST28","Lutz Finger","01M70FMZSMNSQXME0Z705YQQQG",30,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Fskills\u002Fpodcast-download\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"podcast","download","SAI podcast download","spotify","api","you","workflow","manifest","URL","use","local","search","transcribe","for","retry","Audio","downloads","show","as","pull","2026-11-10 10:12:30",false,"---\nname: SAI-podcast-download\ndescription: Atomic SAI skill. Download podcast episode audio from an RSS feed or a Spotify show URL (resolved to RSS via the iTunes Search API — Spotify itself blocks audio downloads). Resume-safe, retry-aware. Emits a manifest.json that downstream skills (local-transcribe, podcast-rag-index) consume. Use whenever you need to download a podcast, grab episodes of a show, pull audio for a Spotify show URL, or any workflow needs raw podcast MP3s as input.\n---\n\n# Trigger manifest — podcast-download (atomic, autonomous)\n\nCode: `skills\u002Fpodcast-download\u002F`\nManifest: `skill.yaml` (4-tier cascade)\nEntry point: `runner.py` → `run(inputs)`\n\n## Cascade plan\n\n```\n1. resolve_feed       (rules) → Spotify URL → RSS via iTunes Search API\n2. list_episodes      (rules) → parse RSS, filter by since_date \u002F max_episodes\n3. download_each      (rules) → fetch missing audio (retries, resume-safe)\n4. write_manifest     (rules) → emit manifest.json; ready_to_propose\n```\n\nAll tiers are deterministic Python. No LLM calls. No external auth required.\n\n## Invocation\n\n```bash\n.venv\u002Fbin\u002Fpython3.12 \\\n  skills\u002Fpodcast-download\u002Frunner.py run \\\n  --inputs-json '{\n    \"spotify_show_url\": \"https:\u002F\u002Fopen.spotify.com\u002Fshow\u002F\u003Cspotify-show-id>\",\n    \"output_dir\":       \"~\u002FMedia\u002Fpodcasts\u002F\u003Cshow-slug>\",\n    \"since_date\":       \"2020-01-01\",\n    \"max_episodes\":     0\n  }'\n```\n\nEither `spotify_show_url` or `feed_url` is required. `max_episodes: 0` means all.\nInvoke runners by absolute path (folder names use hyphens, so `python -m` won't import).\n\n## Standard manifest shape\n\n```json\n{\n  \"workflow_id\": \"podcast-download\",\n  \"feed_url\":    \"https:\u002F\u002F...\u002Ffeed.xml\",\n  \"episodes\": [\n    {\n      \"episode_id\":  \"\u003Csha1-hex>\",\n      \"title\":       \"...\",\n      \"pub_date\":    \"YYYY-MM-DD\",\n      \"audio_path\":  \"\u002Fabs\u002Fpath\u002Fto\u002Ffile.mp3\",\n      \"audio_url\":   \"https:\u002F\u002F...\",\n      \"show_title\":  \"...\"\n    }\n  ],\n  \"download_results\": {\"downloaded\": [...], \"skipped\": [...], \"failed\": [...]}\n}\n```\n\n## Composes with\n\n- `SAI-local-transcribe` — feeds `manifest.episodes[].audio_path` into Whisper\n- `SAI-podcast-rag-index` — writes transcripts into the ChromaDB index\n","# Trigger manifest — podcast-download (atomic, autonomous)\n\nCode: `skills\u002Fpodcast-download\u002F`\nManifest: `skill.yaml` (4-tier cascade)\nEntry point: `runner.py` → `run(inputs)`\n\n## Cascade plan\n\n```\n1. resolve_feed       (rules) → Spotify URL → RSS via iTunes Search API\n2. list_episodes      (rules) → parse RSS, filter by since_date \u002F max_episodes\n3. download_each      (rules) → fetch missing audio (retries, resume-safe)\n4. write_manifest     (rules) → emit manifest.json; ready_to_propose\n```\n\nAll tiers are deterministic Python. No LLM calls. No external auth required.\n\n## Invocation\n\n```bash\n.venv\u002Fbin\u002Fpython3.12 \\\n  skills\u002Fpodcast-download\u002Frunner.py run \\\n  --inputs-json '{\n    \"spotify_show_url\": \"https:\u002F\u002Fopen.spotify.com\u002Fshow\u002F\u003Cspotify-show-id>\",\n    \"output_dir\":       \"~\u002FMedia\u002Fpodcasts\u002F\u003Cshow-slug>\",\n    \"since_date\":       \"2020-01-01\",\n    \"max_episodes\":     0\n  }'\n```\n\nEither `spotify_show_url` or `feed_url` is required. `max_episodes: 0` means all.\nInvoke runners by absolute path (folder names use hyphens, so `python -m` won't import).\n\n## Standard manifest shape\n\n```json\n{\n  \"workflow_id\": \"podcast-download\",\n  \"feed_url\":    \"https:\u002F\u002F...\u002Ffeed.xml\",\n  \"episodes\": [\n    {\n      \"episode_id\":  \"\u003Csha1-hex>\",\n      \"title\":       \"...\",\n      \"pub_date\":    \"YYYY-MM-DD\",\n      \"audio_path\":  \"\u002Fabs\u002Fpath\u002Fto\u002Ffile.mp3\",\n      \"audio_url\":   \"https:\u002F\u002F...\",\n      \"show_title\":  \"...\"\n    }\n  ],\n  \"download_results\": {\"downloaded\": [...], \"skipped\": [...], \"failed\": [...]}\n}\n```\n\n## Composes with\n\n- `SAI-local-transcribe` — feeds `manifest.episodes[].audio_path` into Whisper\n- `SAI-podcast-rag-index` — writes transcripts into the ChromaDB index\n",{"name":5,"description":7},"main","230c0cbe27ddb69dff12b1fb9dbfff72098be4d8","skills\u002Fpodcast-download",14,"https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion","https:\u002F\u002Fgithub.com\u002Flutzfinger","lutzfinger.com","Chief AI Officer · OMMAX \r\nData Scientist in Residence · Cornell SC Johnson College of Business\r\nVenture Partner · Cherry Ventures","2026-07-17 14:56:40",{"source":8,"skillName":5,"commands":59,"prompt":69,"zipAvailable":70},[60,63,66],{"tool":61,"command":62},"npx","npx skills add lutzfinger\u002FSAI-baseversion --skill SAI-podcast-download",{"tool":64,"command":65},"bunx","bunx skills add lutzfinger\u002FSAI-baseversion --skill SAI-podcast-download",{"tool":67,"command":68},"pnpm","pnpm dlx skills add lutzfinger\u002FSAI-baseversion --skill SAI-podcast-download","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Fskills\u002Fpodcast-download\u002FSKILL.md",true,[72,78,82,86,92,98,102],{"path":73,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":76,"sourceHtmlUrl":77},"canaries.jsonl","OTHER","其他",344,"https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Fskills\u002Fpodcast-download\u002Fcanaries.jsonl",{"path":79,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":80,"sourceHtmlUrl":81},"edge_cases.jsonl",782,"https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Fskills\u002Fpodcast-download\u002Fedge_cases.jsonl",{"path":83,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":84,"sourceHtmlUrl":85},"profiles\u002Fclaude_code\u002Fcanaries.jsonl",661,"https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Fskills\u002Fpodcast-download\u002Fprofiles\u002Fclaude_code\u002Fcanaries.jsonl",{"path":87,"resourceType":88,"resourceTypeDesc":89,"sizeBytes":90,"sourceHtmlUrl":91},"README.md","REFERENCE","参考文档",1914,"https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Fskills\u002Fpodcast-download\u002FREADME.md",{"path":93,"resourceType":94,"resourceTypeDesc":95,"sizeBytes":96,"sourceHtmlUrl":97},"runner.py","SCRIPT","脚本",10397,"https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Fskills\u002Fpodcast-download\u002Frunner.py",{"path":99,"resourceType":88,"resourceTypeDesc":89,"sizeBytes":100,"sourceHtmlUrl":101},"skill.yaml",2426,"https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Fskills\u002Fpodcast-download\u002Fskill.yaml",{"path":103,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":104,"sourceHtmlUrl":105},"workflow_regression.jsonl",673,"https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Fskills\u002Fpodcast-download\u002Fworkflow_regression.jsonl",[107,115,128,150,172],{"skillNo":108,"name":109,"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":110,"categories":111,"keywords":112,"publishedAt":44},"01M70FNHF7QQ2S5ZGXY379VHGH","sample-glob","https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Ftests\u002Fruntime\u002Ffixtures\u002Foverlay_deploy\u002Fskills\u002Fsample-glob\u002FSKILL.md",[],[113,114],"sample glob","sample",{"skillNo":116,"name":117,"nameZh":6,"description":118,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":121,"publishedAt":44},"01M70FNFS1JSPPYWQ3C7AA3KPY","sample-alpha","Synthetic skill for sai-overlay deploy tests. Not a real skill.","https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Ftests\u002Fruntime\u002Ffixtures\u002Foverlay_deploy\u002Fskills\u002Fsample-alpha\u002FSKILL.md",[],[122,123,114,124,125,126,37,127],"alpha","sample alpha","tests","deploy","overlay","synthetic",{"skillNo":129,"name":130,"nameZh":6,"description":131,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":132,"categories":133,"keywords":134,"publishedAt":44},"01M70FNDBVZRBGMJBX84BS50ZW","sample-incoming","Fixture for PR 7 (scaffold-claude-code-skill). Simulates a Claude-Code\nskill discovered in the plugin-install path with no skill.yaml manifest.\nThe scaffold subcommand reads this dir and emits a starter skill.yaml v2\nwith a single claude_code profile.","https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Ftests\u002Fruntime\u002Ffixtures\u002Foverlay_deploy\u002Fscaffold\u002Finput\u002Fsample-incoming\u002FSKILL.md",[],[135,114,136,137,138,139,140,37,141,142,143,144,31,145,146,147,148,149],"sample incoming","with","fixture","starter","plugin","pr","yaml","install","single","code skill","claude-code","code","scaffold","profile","path",{"skillNo":151,"name":152,"nameZh":6,"description":153,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":154,"categories":155,"keywords":156,"publishedAt":44},"01M70FN9WYSGBEFXQ28BM5F8ES","SAI-podcast-rag-index","Atomic SAI skill. Index a directory of transcript .md files (YAML frontmatter, one per episode) into an existing ChromaDB RAG store by delegating to a rag-index-updater-style index.py. Pure mechanism — no operator paths or collection baked in; the caller supplies indexer_scripts \u002F manifest_path directly or via a private config_path. Hash-skips unchanged files. Use whenever you need to index transcripts, add transcripts to a RAG, or embed episodes for semantic lookup.","https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Fskills\u002Fpodcast-rag-index\u002FSKILL.md",[],[24,157,158,159,33,37,160,161,31,29,162,163,164,165,166,167,168,169,170,171],"index","rag","SAI podcast rag index","files","Existing","collection","indexer","embed","transcript","store","updater","style","via","directory","scripts",{"skillNo":173,"name":174,"nameZh":6,"description":175,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":176,"categories":177,"keywords":179,"publishedAt":44},"01M70FN4CNMY7TJ90T0G6Q0A9Q","SAI-local-transcribe","Atomic SAI skill. Fully-local audio transcription via Whisper (mlx-whisper on Apple Silicon, faster-whisper fallback elsewhere). No audio leaves the machine; no API keys. Accepts a single audio file, a directory, or a podcast-download manifest.json. Writes one .md per input with YAML frontmatter compatible with a rag-index-updater pipeline. Use whenever you need to transcribe audio, run whisper on a file, transcribe all episodes in a folder, or any workflow needs text from audio.","https:\u002F\u002Fgithub.com\u002Flutzfinger\u002FSAI-baseversion\u002Fblob\u002Fmain\u002Fskills\u002Flocal-transcribe\u002FSKILL.md",[178],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[34,36,180,181,182,183,184,39,185,28,186,167,187,136,188,30,31,33,143,29],"SAI local transcribe","machine","apple silicon","pipeline","api keys","file","mlx","text","whisper"]