[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6BV6X8R8D2V8T8BMP1ZW7Q8":3,"skill-same:01M6BV6X8R8D2V8T8BMP1ZW7Q8":69},{"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":34,"linkOnly":35,"markdownContent":36,"markdownBody":37,"frontMatter":38,"refName":39,"commitSha":40,"skillDirectory":41,"forksCount":14,"repositoryHtmlUrl":42,"repositoryHomepageUrl":6,"ownerHtmlUrl":43,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":44,"install":45,"resources":58},"01M6BV6X8R8D2V8T8BMP1ZW7Q8","migrate-to-shoehorn",null,"Migrate test files from `as` type assertions to @total-typescript\u002Fshoehorn. Use when user mentions shoehorn, wants to replace `as` in tests, or needs partial test data.","bnferguson\u002Fdotfiles","bnferguson","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F47749?v=4","01M6BV4H2TJKK8P14W86V1ZCPP","Brandon Ferguson","01M6BV4H7GJWTZJ1BVHQ1TX11Y",0,"MIT","https:\u002F\u002Fgithub.com\u002Fbnferguson\u002Fdotfiles\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fmigrate-to-shoehorn\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33],"migrate to shoehorn","migrate","typescript","test","data","user","use","files","test data","tests","as","type","assertions","when","replace","2026-11-10 10:12:30",false,"---\nname: migrate-to-shoehorn\ndescription: Migrate test files from `as` type assertions to @total-typescript\u002Fshoehorn. Use when user mentions shoehorn, wants to replace `as` in tests, or needs partial test data.\n---\n\n# Migrate to Shoehorn\n\n## Why shoehorn?\n\n`shoehorn` lets you pass partial data in tests while keeping TypeScript happy. It replaces `as` assertions with type-safe alternatives.\n\n**Test code only.** Never use shoehorn in production code.\n\nProblems with `as` in tests:\n\n- Trained not to use it\n- Must manually specify target type\n- Double-as (`as unknown as Type`) for intentionally wrong data\n\n## Install\n\n```bash\nnpm i @total-typescript\u002Fshoehorn\n```\n\n## Migration patterns\n\n### Large objects with few needed properties\n\nBefore:\n\n```ts\ntype Request = {\n  body: { id: string };\n  headers: Record\u003Cstring, string>;\n  cookies: Record\u003Cstring, string>;\n  \u002F\u002F ...20 more properties\n};\n\nit(\"gets user by id\", () => {\n  \u002F\u002F Only care about body.id but must fake entire Request\n  getUser({\n    body: { id: \"123\" },\n    headers: {},\n    cookies: {},\n    \u002F\u002F ...fake all 20 properties\n  });\n});\n```\n\nAfter:\n\n```ts\nimport { fromPartial } from \"@total-typescript\u002Fshoehorn\";\n\nit(\"gets user by id\", () => {\n  getUser(\n    fromPartial({\n      body: { id: \"123\" },\n    }),\n  );\n});\n```\n\n### `as Type` → `fromPartial()`\n\nBefore:\n\n```ts\ngetUser({ body: { id: \"123\" } } as Request);\n```\n\nAfter:\n\n```ts\nimport { fromPartial } from \"@total-typescript\u002Fshoehorn\";\n\ngetUser(fromPartial({ body: { id: \"123\" } }));\n```\n\n### `as unknown as Type` → `fromAny()`\n\nBefore:\n\n```ts\ngetUser({ body: { id: 123 } } as unknown as Request); \u002F\u002F wrong type on purpose\n```\n\nAfter:\n\n```ts\nimport { fromAny } from \"@total-typescript\u002Fshoehorn\";\n\ngetUser(fromAny({ body: { id: 123 } }));\n```\n\n## When to use each\n\n| Function        | Use case                                           |\n| --------------- | -------------------------------------------------- |\n| `fromPartial()` | Pass partial data that still type-checks           |\n| `fromAny()`     | Pass intentionally wrong data (keeps autocomplete) |\n| `fromExact()`   | Force full object (swap with fromPartial later)    |\n\n## Workflow\n\n1. **Gather requirements** - ask user:\n   - What test files have `as` assertions causing problems?\n   - Are they dealing with large objects where only some properties matter?\n   - Do they need to pass intentionally wrong data for error testing?\n\n2. **Install and migrate**:\n   - [ ] Install: `npm i @total-typescript\u002Fshoehorn`\n   - [ ] Find test files with `as` assertions: `grep -r \" as [A-Z]\" --include=\"*.test.ts\" --include=\"*.spec.ts\"`\n   - [ ] Replace `as Type` with `fromPartial()`\n   - [ ] Replace `as unknown as Type` with `fromAny()`\n   - [ ] Add imports from `@total-typescript\u002Fshoehorn`\n   - [ ] Run type check to verify\n","# Migrate to Shoehorn\n\n## Why shoehorn?\n\n`shoehorn` lets you pass partial data in tests while keeping TypeScript happy. It replaces `as` assertions with type-safe alternatives.\n\n**Test code only.** Never use shoehorn in production code.\n\nProblems with `as` in tests:\n\n- Trained not to use it\n- Must manually specify target type\n- Double-as (`as unknown as Type`) for intentionally wrong data\n\n## Install\n\n```bash\nnpm i @total-typescript\u002Fshoehorn\n```\n\n## Migration patterns\n\n### Large objects with few needed properties\n\nBefore:\n\n```ts\ntype Request = {\n  body: { id: string };\n  headers: Record\u003Cstring, string>;\n  cookies: Record\u003Cstring, string>;\n  \u002F\u002F ...20 more properties\n};\n\nit(\"gets user by id\", () => {\n  \u002F\u002F Only care about body.id but must fake entire Request\n  getUser({\n    body: { id: \"123\" },\n    headers: {},\n    cookies: {},\n    \u002F\u002F ...fake all 20 properties\n  });\n});\n```\n\nAfter:\n\n```ts\nimport { fromPartial } from \"@total-typescript\u002Fshoehorn\";\n\nit(\"gets user by id\", () => {\n  getUser(\n    fromPartial({\n      body: { id: \"123\" },\n    }),\n  );\n});\n```\n\n### `as Type` → `fromPartial()`\n\nBefore:\n\n```ts\ngetUser({ body: { id: \"123\" } } as Request);\n```\n\nAfter:\n\n```ts\nimport { fromPartial } from \"@total-typescript\u002Fshoehorn\";\n\ngetUser(fromPartial({ body: { id: \"123\" } }));\n```\n\n### `as unknown as Type` → `fromAny()`\n\nBefore:\n\n```ts\ngetUser({ body: { id: 123 } } as unknown as Request); \u002F\u002F wrong type on purpose\n```\n\nAfter:\n\n```ts\nimport { fromAny } from \"@total-typescript\u002Fshoehorn\";\n\ngetUser(fromAny({ body: { id: 123 } }));\n```\n\n## When to use each\n\n| Function        | Use case                                           |\n| --------------- | -------------------------------------------------- |\n| `fromPartial()` | Pass partial data that still type-checks           |\n| `fromAny()`     | Pass intentionally wrong data (keeps autocomplete) |\n| `fromExact()`   | Force full object (swap with fromPartial later)    |\n\n## Workflow\n\n1. **Gather requirements** - ask user:\n   - What test files have `as` assertions causing problems?\n   - Are they dealing with large objects where only some properties matter?\n   - Do they need to pass intentionally wrong data for error testing?\n\n2. **Install and migrate**:\n   - [ ] Install: `npm i @total-typescript\u002Fshoehorn`\n   - [ ] Find test files with `as` assertions: `grep -r \" as [A-Z]\" --include=\"*.test.ts\" --include=\"*.spec.ts\"`\n   - [ ] Replace `as Type` with `fromPartial()`\n   - [ ] Replace `as unknown as Type` with `fromAny()`\n   - [ ] Add imports from `@total-typescript\u002Fshoehorn`\n   - [ ] Run type check to verify\n",{"name":5,"description":7},"main","e63965e4644984470d4cc8b3014a8b001f0c2666",".agents\u002Fskills\u002Fmigrate-to-shoehorn","https:\u002F\u002Fgithub.com\u002Fbnferguson\u002Fdotfiles","https:\u002F\u002Fgithub.com\u002Fbnferguson","2026-11-11 03:04:59",{"source":8,"skillName":5,"commands":46,"prompt":56,"zipAvailable":57},[47,50,53],{"tool":48,"command":49},"npx","npx skills add bnferguson\u002Fdotfiles --skill migrate-to-shoehorn",{"tool":51,"command":52},"bunx","bunx skills add bnferguson\u002Fdotfiles --skill migrate-to-shoehorn",{"tool":54,"command":55},"pnpm","pnpm dlx skills add bnferguson\u002Fdotfiles --skill migrate-to-shoehorn","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fbnferguson\u002Fdotfiles\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fmigrate-to-shoehorn\u002FSKILL.md",true,[59,65],{"path":60,"resourceType":61,"resourceTypeDesc":62,"sizeBytes":63,"sourceHtmlUrl":64},"agents\u002Fopenai.yaml","REFERENCE","参考文档",110,"https:\u002F\u002Fgithub.com\u002Fbnferguson\u002Fdotfiles\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fmigrate-to-shoehorn\u002Fagents\u002Fopenai.yaml",{"path":66,"resourceType":61,"resourceTypeDesc":62,"sizeBytes":67,"sourceHtmlUrl":68},"references\u002Fjleechanorg-automation-topology.md",5690,"https:\u002F\u002Fgithub.com\u002Fjleechanorg\u002Fjleechan-skills\u002Fblob\u002Fmain\u002Fhermes\u002Fskills\u002Fgithub\u002Fgithub-pr-automation-debug\u002Freferences\u002Fjleechanorg-automation-topology.md",[70,102,119,148,157,170],{"skillNo":71,"name":72,"nameZh":6,"description":73,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":74,"licenseFileUrl":75,"sourceHtmlUrl":76,"categories":77,"keywords":83,"publishedAt":34},"01M6BVA3RS3M016FANZ6792F9H","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.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fbnferguson\u002Fdotfiles\u002Fblob\u002Fmain\u002Fclaude\u002Fconfig\u002Fskills\u002Fskill-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fbnferguson\u002Fdotfiles\u002Fblob\u002Fmain\u002Fclaude\u002Fconfig\u002Fskills\u002Fskill-creator\u002FSKILL.md",[78],{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,32,101],"creator","skill creator","specialized","workflows","create","update","capabilities","knowledge","tool","integrations","guide","new skill","existing skill","users","with","for","Existing","new",{"skillNo":103,"name":104,"nameZh":6,"description":105,"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":116,"publishedAt":34},"01M6BV94WN2RPYM8N6PN8TBNT8","writing-shape","Writing, exploit: shape raw material into an article, paragraph by paragraph.","https:\u002F\u002Fgithub.com\u002Fbnferguson\u002Fdotfiles\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fwriting-shape\u002FSKILL.md",[108,111],{"categoryNo":109,"categoryName":110,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":112,"categoryName":113,"taxonomyType":114,"taxonomyTypeDesc":115},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[117,118],"writing shape","writing",{"skillNo":120,"name":121,"nameZh":6,"description":122,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":74,"licenseFileUrl":123,"sourceHtmlUrl":124,"categories":125,"keywords":132,"publishedAt":34},"01M6BV8QDFJ6PXBVK5NFBZT5M7","webapp-testing","Test local web applications using Playwright. Use when verifying frontend functionality, debugging UI behavior, capturing browser screenshots, or viewing browser logs.","https:\u002F\u002Fgithub.com\u002Fbnferguson\u002Fdotfiles\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fwebapp-testing\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fbnferguson\u002Fdotfiles\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fwebapp-testing\u002FSKILL.md",[126,129],{"categoryNo":127,"categoryName":128,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":130,"categoryName":131,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000009","前端开发",[133,134,135,136,137,138,139,22,140,141,142,143,144,145,25,146,147,32],"webapp","webapp testing","testing","browser","frontend","screenshots","playwright","web","debugging","ui","logs","applications","behavior","local","test local",{"skillNo":149,"name":150,"nameZh":6,"description":151,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":152,"categories":153,"keywords":154,"publishedAt":34},"01M6BV8MDXKXNVHKS3QF3YDFTF","wait-what","Stop. That last message did not land: re-pitch it.","https:\u002F\u002Fgithub.com\u002Fbnferguson\u002Fdotfiles\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fwait-what\u002FSKILL.md",[],[155,156],"wait what","land",{"skillNo":158,"name":159,"nameZh":6,"description":160,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":161,"categories":162,"keywords":166,"publishedAt":34},"01M6BV756DJHT5BDA1HVRVHJJ7","prototype","Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.","https:\u002F\u002Fgithub.com\u002Fbnferguson\u002Fdotfiles\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fprototype\u002FSKILL.md",[163],{"categoryNo":164,"categoryName":165,"taxonomyType":114,"taxonomyTypeDesc":115},"01JBSEEDCAT000000000000032","设计师",[159,167,168,142,169],"design","explore","state",{"skillNo":171,"name":172,"nameZh":6,"description":173,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":174,"categories":175,"keywords":177,"publishedAt":34},"01M6BV6SBW166685KVBPWM2K4N","improve-codebase-architecture","Scan a codebase for deepening opportunities, present them as a visual HTML report, then grill through whichever one you pick.","https:\u002F\u002Fgithub.com\u002Fbnferguson\u002Fdotfiles\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fimprove-codebase-architecture\u002FSKILL.md",[176],{"categoryNo":130,"categoryName":131,"taxonomyType":81,"taxonomyTypeDesc":82},[178,179,180,181],"architecture","improve","improve codebase architecture","report"]