[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71SX8KMQT31ARMDTDMZ73B8":3,"skill-same:01M71SX8KMQT31ARMDTDMZ73B8":66},{"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":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":44,"commitSha":45,"skillDirectory":46,"forksCount":47,"repositoryHtmlUrl":48,"repositoryHomepageUrl":6,"ownerHtmlUrl":49,"ownerBlogUrl":50,"ownerDescription":6,"updatedAt":51,"install":52,"resources":65},"01M71SX8KMQT31ARMDTDMZ73B8","pi-extension-builder",null,"Build, debug, and package pi coding-agent extensions. Use when the user wants to create or modify a pi extension, register custom tools or commands, handle lifecycle events, or package extensions for sharing.","Artawower\u002Fkaizen","Artawower","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F16963833?v=4","01M71SV5H0DRR8KXVGD4R51Z99","Art","01M71SV5J1B97T7349GGXQCYXT",2,"GPL-3.0","https:\u002F\u002Fgithub.com\u002FArtawower\u002Fkaizen\u002Fblob\u002Fmaster\u002Fdotfiles\u002Fdot_agents\u002Fskills\u002Fpi-extension-builder\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"pi","pi extension","extension","pi extension builder","builder","commands","sharing","build","create","extensions","when","debug","use","package","custom","handle","lifecycle","for","register","modify","2026-11-10 13:02:02",false,"---\nname: pi-extension-builder\ndescription: Build, debug, and package pi coding-agent extensions. Use when the user wants to create or modify a pi extension, register custom tools or commands, handle lifecycle events, or package extensions for sharing.\n---\n\n# Pi Extension Builder\n\n> **Freshness**: Fetch live docs when implementing event handlers, stateful tools, file-mutating tools, or custom rendering:\n> `fetch_content https:\u002F\u002Fraw.githubusercontent.com\u002Fbadlogic\u002Fpi-mono\u002Frefs\u002Fheads\u002Fmain\u002Fpackages\u002Fcoding-agent\u002Fdocs\u002Fextensions.md`\n\n---\n\n## Pre-conditions\n\n1. Check for existing extensions before creating a new one:\n   - Global: `~\u002F.pi\u002Fagent\u002Fextensions\u002F`\n   - Project-local: `.pi\u002Fextensions\u002F`\n2. Confirm with the user: global or project-local scope?\n3. Are npm dependencies needed? → determines extension structure below.\n\n---\n\n## What are you building?\n\n| Goal                                      | Tool                                                                      |\n| ----------------------------------------- | ------------------------------------------------------------------------- |\n| Custom tool for the LLM                   | `pi.registerTool()`                                                       |\n| Slash command `\u002Fmycommand`                | `pi.registerCommand()`                                                    |\n| Block a tool call                         | `pi.on(\"tool_call\")` → `return { block: true, reason? }`                  |\n| Modify tool call arguments                | `pi.on(\"tool_call\")` → mutate `event.input` in place (return only blocks) |\n| Modify tool output                        | `pi.on(\"tool_result\")` → `return { content?, details?, isError? }`        |\n| Intercept user input                      | `pi.on(\"input\")` → `return { action: \"transform\", text: ... }`            |\n| Inject context before each turn           | `pi.on(\"before_agent_start\")` → `return { message?, systemPrompt? }`      |\n| User interaction (confirm, select, input) | `ctx.ui.*`                                                                |\n| Custom TUI rendering                      | `renderCall` \u002F `renderResult`                                             |\n| Register dynamic skills\u002Fprompts\u002Fthemes    | `pi.on(\"resources_discover\")` → `return { skillPaths?, promptPaths?, themePaths? }` |\n| Override built-in tool (bash, read, write…) | `pi.registerTool({ name: \"bash\", ... })` — same name replaces built-in |\n| Persist state across sessions             | `pi.appendEntry()` \u002F `details` pattern                                    |\n| Share via npm\u002Fgit                         | `package.json` with `pi` key                                              |\n\n---\n\n## Extension structure\n\n**Single file** (simple extensions):\n\n```\n~\u002F.pi\u002Fagent\u002Fextensions\u002Fmy-extension.ts\n```\n\n**Directory** (multiple modules):\n\n```\n~\u002F.pi\u002Fagent\u002Fextensions\u002Fmy-extension\u002F\n├── index.ts\n└── helpers.ts\n```\n\n**Package** (needs npm dependencies):\n\n```\n~\u002F.pi\u002Fagent\u002Fextensions\u002Fmy-extension\u002F\n├── package.json    # with \"pi\" key\n├── node_modules\u002F\n└── src\u002Findex.ts\n```\n\n`package.json` for a package:\n\n```json\n{\n  \"name\": \"my-extension\",\n  \"dependencies\": { \"zod\": \"^3.0.0\" },\n  \"pi\": { \"extensions\": [\".\u002Fsrc\u002Findex.ts\"] }\n}\n```\n\n---\n\n## Extension skeleton\n\n```ts\nimport type { ExtensionAPI } from \"@mariozechner\u002Fpi-coding-agent\";\nimport {\n  truncateHead,\n  DEFAULT_MAX_BYTES,\n  DEFAULT_MAX_LINES,\n} from \"@mariozechner\u002Fpi-coding-agent\";\nimport { Type } from \"@sinclair\u002Ftypebox\";\nimport { StringEnum } from \"@mariozechner\u002Fpi-ai\"; \u002F\u002F required for Google model compatibility\n\nexport default function (pi: ExtensionAPI) {\n  pi.registerTool({\n    name: \"my_tool\",\n    label: \"My Tool\",\n    description: \"What this tool does (shown to LLM)\",\n    promptSnippet:\n      \"One-liner for Available tools section — omit and LLM won't discover this tool\",\n    parameters: Type.Object({\n      action: StringEnum([\"list\", \"add\"] as const),\n    }),\n    async execute(toolCallId, params, signal, onUpdate, ctx) {\n      if (signal?.aborted)\n        return { content: [{ type: \"text\", text: \"Cancelled\" }] };\n\n      \u002F\u002F throw to signal failure — returning any value always succeeds (isError: false)\n      const { stdout } = await pi.exec(\"git\", [\"status\"], { signal });\n\n      const truncation = truncateHead(stdout, {\n        maxLines: DEFAULT_MAX_LINES,\n        maxBytes: DEFAULT_MAX_BYTES,\n      });\n      return { content: [{ type: \"text\", text: truncation.content }] };\n    },\n  });\n\n  pi.on(\"session_shutdown\", async () => {\n    \u002F\u002F close connections, file watchers, timers\n  });\n}\n```\n\n---\n\n## Workflow\n\n1. **Define the goal** — tool, command, event handler, or a combination\n2. **Choose scope** — global vs project-local\n3. **Choose structure** — single file \u002F directory \u002F package\n4. **Scaffold** — `export default function (pi: ExtensionAPI) { ... }`\n5. **Register capabilities** — `registerTool`, `registerCommand`, `pi.on`\n6. **Handle state** — decide if `details` pattern is needed for reconstruction\n7. **Test** — `pi -e .\u002Fextension.ts` or `\u002Freload` after placing in auto-discovery path\n8. **Package if needed** — add `package.json` with `pi` key for sharing\n\n---\n\n## Critical pitfalls\n\n- **Google compatibility**: use `StringEnum([\"a\", \"b\"] as const)`, never `Type.Enum()` or union types\n- **Error signaling**: `throw new Error(...)` from `execute()` to report failure — returning any value always succeeds (`isError: false`)\n- **Output truncation**: use `truncateHead`\u002F`truncateTail` from `@mariozechner\u002Fpi-coding-agent` for output over 50KB\u002F2000 lines — untruncated output breaks context\n- **promptSnippet**: without it, the LLM won't see the tool in the `Available tools` section and won't discover it\n- **tool_call mutation**: return `{ block: true }` to block, mutate `event.input` in place to modify args — return value does NOT modify arguments\n- **Non-interactive modes**: always check `ctx.hasUI` before calling UI methods\n- **State and branches**: store state in tool result `details`; reconstruct from `ctx.sessionManager.getBranch()` in BOTH `session_start` AND `session_tree` (tree navigation fires `session_tree`, not `session_start`)\n- **File-mutating tools**: wrap with `withFileMutationQueue()` — tool calls run in parallel, without the queue concurrent edits to the same file will clobber each other\n- **sendUserMessage during streaming**: must pass `{ deliverAs: \"steer\" | \"followUp\" }` — calling without it while agent is streaming throws\n- **Cleanup**: always register `session_shutdown` for connections, file watchers, timers\n- **Reload is terminal**: code after `await ctx.reload()` is not guaranteed to run — treat it as the last statement\n\n---\n\n## Placement and scope\n\n| Path                                | Scope                 | Hot-reload      |\n| ----------------------------------- | --------------------- | --------------- |\n| `~\u002F.pi\u002Fagent\u002Fextensions\u002F*.ts`       | Global                | Yes (`\u002Freload`) |\n| `~\u002F.pi\u002Fagent\u002Fextensions\u002F*\u002Findex.ts` | Global (subdirectory) | Yes             |\n| `.pi\u002Fextensions\u002F*.ts`               | Project-local         | Yes             |\n| `pi -e .\u002Fpath.ts`                   | One-time test         | No              |\n\n---\n\n## Available imports (no npm install needed)\n\n| Package                         | Purpose                                                                                           |\n| ------------------------------- | ------------------------------------------------------------------------------------------------- |\n| `@mariozechner\u002Fpi-coding-agent` | `ExtensionAPI`, event types, type guards, `truncateHead`, `truncateTail`, `withFileMutationQueue` |\n| `@sinclair\u002Ftypebox`             | `Type.Object`, `Type.String`, etc. for parameters                                                 |\n| `@mariozechner\u002Fpi-ai`           | `StringEnum` for Google-compatible enums                                                          |\n| `@mariozechner\u002Fpi-tui`          | `Text`, `Box`, `List`, `Input`, `Select`                                                          |\n","# Pi Extension Builder\n\n> **Freshness**: Fetch live docs when implementing event handlers, stateful tools, file-mutating tools, or custom rendering:\n> `fetch_content https:\u002F\u002Fraw.githubusercontent.com\u002Fbadlogic\u002Fpi-mono\u002Frefs\u002Fheads\u002Fmain\u002Fpackages\u002Fcoding-agent\u002Fdocs\u002Fextensions.md`\n\n---\n\n## Pre-conditions\n\n1. Check for existing extensions before creating a new one:\n   - Global: `~\u002F.pi\u002Fagent\u002Fextensions\u002F`\n   - Project-local: `.pi\u002Fextensions\u002F`\n2. Confirm with the user: global or project-local scope?\n3. Are npm dependencies needed? → determines extension structure below.\n\n---\n\n## What are you building?\n\n| Goal                                      | Tool                                                                      |\n| ----------------------------------------- | ------------------------------------------------------------------------- |\n| Custom tool for the LLM                   | `pi.registerTool()`                                                       |\n| Slash command `\u002Fmycommand`                | `pi.registerCommand()`                                                    |\n| Block a tool call                         | `pi.on(\"tool_call\")` → `return { block: true, reason? }`                  |\n| Modify tool call arguments                | `pi.on(\"tool_call\")` → mutate `event.input` in place (return only blocks) |\n| Modify tool output                        | `pi.on(\"tool_result\")` → `return { content?, details?, isError? }`        |\n| Intercept user input                      | `pi.on(\"input\")` → `return { action: \"transform\", text: ... }`            |\n| Inject context before each turn           | `pi.on(\"before_agent_start\")` → `return { message?, systemPrompt? }`      |\n| User interaction (confirm, select, input) | `ctx.ui.*`                                                                |\n| Custom TUI rendering                      | `renderCall` \u002F `renderResult`                                             |\n| Register dynamic skills\u002Fprompts\u002Fthemes    | `pi.on(\"resources_discover\")` → `return { skillPaths?, promptPaths?, themePaths? }` |\n| Override built-in tool (bash, read, write…) | `pi.registerTool({ name: \"bash\", ... })` — same name replaces built-in |\n| Persist state across sessions             | `pi.appendEntry()` \u002F `details` pattern                                    |\n| Share via npm\u002Fgit                         | `package.json` with `pi` key                                              |\n\n---\n\n## Extension structure\n\n**Single file** (simple extensions):\n\n```\n~\u002F.pi\u002Fagent\u002Fextensions\u002Fmy-extension.ts\n```\n\n**Directory** (multiple modules):\n\n```\n~\u002F.pi\u002Fagent\u002Fextensions\u002Fmy-extension\u002F\n├── index.ts\n└── helpers.ts\n```\n\n**Package** (needs npm dependencies):\n\n```\n~\u002F.pi\u002Fagent\u002Fextensions\u002Fmy-extension\u002F\n├── package.json    # with \"pi\" key\n├── node_modules\u002F\n└── src\u002Findex.ts\n```\n\n`package.json` for a package:\n\n```json\n{\n  \"name\": \"my-extension\",\n  \"dependencies\": { \"zod\": \"^3.0.0\" },\n  \"pi\": { \"extensions\": [\".\u002Fsrc\u002Findex.ts\"] }\n}\n```\n\n---\n\n## Extension skeleton\n\n```ts\nimport type { ExtensionAPI } from \"@mariozechner\u002Fpi-coding-agent\";\nimport {\n  truncateHead,\n  DEFAULT_MAX_BYTES,\n  DEFAULT_MAX_LINES,\n} from \"@mariozechner\u002Fpi-coding-agent\";\nimport { Type } from \"@sinclair\u002Ftypebox\";\nimport { StringEnum } from \"@mariozechner\u002Fpi-ai\"; \u002F\u002F required for Google model compatibility\n\nexport default function (pi: ExtensionAPI) {\n  pi.registerTool({\n    name: \"my_tool\",\n    label: \"My Tool\",\n    description: \"What this tool does (shown to LLM)\",\n    promptSnippet:\n      \"One-liner for Available tools section — omit and LLM won't discover this tool\",\n    parameters: Type.Object({\n      action: StringEnum([\"list\", \"add\"] as const),\n    }),\n    async execute(toolCallId, params, signal, onUpdate, ctx) {\n      if (signal?.aborted)\n        return { content: [{ type: \"text\", text: \"Cancelled\" }] };\n\n      \u002F\u002F throw to signal failure — returning any value always succeeds (isError: false)\n      const { stdout } = await pi.exec(\"git\", [\"status\"], { signal });\n\n      const truncation = truncateHead(stdout, {\n        maxLines: DEFAULT_MAX_LINES,\n        maxBytes: DEFAULT_MAX_BYTES,\n      });\n      return { content: [{ type: \"text\", text: truncation.content }] };\n    },\n  });\n\n  pi.on(\"session_shutdown\", async () => {\n    \u002F\u002F close connections, file watchers, timers\n  });\n}\n```\n\n---\n\n## Workflow\n\n1. **Define the goal** — tool, command, event handler, or a combination\n2. **Choose scope** — global vs project-local\n3. **Choose structure** — single file \u002F directory \u002F package\n4. **Scaffold** — `export default function (pi: ExtensionAPI) { ... }`\n5. **Register capabilities** — `registerTool`, `registerCommand`, `pi.on`\n6. **Handle state** — decide if `details` pattern is needed for reconstruction\n7. **Test** — `pi -e .\u002Fextension.ts` or `\u002Freload` after placing in auto-discovery path\n8. **Package if needed** — add `package.json` with `pi` key for sharing\n\n---\n\n## Critical pitfalls\n\n- **Google compatibility**: use `StringEnum([\"a\", \"b\"] as const)`, never `Type.Enum()` or union types\n- **Error signaling**: `throw new Error(...)` from `execute()` to report failure — returning any value always succeeds (`isError: false`)\n- **Output truncation**: use `truncateHead`\u002F`truncateTail` from `@mariozechner\u002Fpi-coding-agent` for output over 50KB\u002F2000 lines — untruncated output breaks context\n- **promptSnippet**: without it, the LLM won't see the tool in the `Available tools` section and won't discover it\n- **tool_call mutation**: return `{ block: true }` to block, mutate `event.input` in place to modify args — return value does NOT modify arguments\n- **Non-interactive modes**: always check `ctx.hasUI` before calling UI methods\n- **State and branches**: store state in tool result `details`; reconstruct from `ctx.sessionManager.getBranch()` in BOTH `session_start` AND `session_tree` (tree navigation fires `session_tree`, not `session_start`)\n- **File-mutating tools**: wrap with `withFileMutationQueue()` — tool calls run in parallel, without the queue concurrent edits to the same file will clobber each other\n- **sendUserMessage during streaming**: must pass `{ deliverAs: \"steer\" | \"followUp\" }` — calling without it while agent is streaming throws\n- **Cleanup**: always register `session_shutdown` for connections, file watchers, timers\n- **Reload is terminal**: code after `await ctx.reload()` is not guaranteed to run — treat it as the last statement\n\n---\n\n## Placement and scope\n\n| Path                                | Scope                 | Hot-reload      |\n| ----------------------------------- | --------------------- | --------------- |\n| `~\u002F.pi\u002Fagent\u002Fextensions\u002F*.ts`       | Global                | Yes (`\u002Freload`) |\n| `~\u002F.pi\u002Fagent\u002Fextensions\u002F*\u002Findex.ts` | Global (subdirectory) | Yes             |\n| `.pi\u002Fextensions\u002F*.ts`               | Project-local         | Yes             |\n| `pi -e .\u002Fpath.ts`                   | One-time test         | No              |\n\n---\n\n## Available imports (no npm install needed)\n\n| Package                         | Purpose                                                                                           |\n| ------------------------------- | ------------------------------------------------------------------------------------------------- |\n| `@mariozechner\u002Fpi-coding-agent` | `ExtensionAPI`, event types, type guards, `truncateHead`, `truncateTail`, `withFileMutationQueue` |\n| `@sinclair\u002Ftypebox`             | `Type.Object`, `Type.String`, etc. for parameters                                                 |\n| `@mariozechner\u002Fpi-ai`           | `StringEnum` for Google-compatible enums                                                          |\n| `@mariozechner\u002Fpi-tui`          | `Text`, `Box`, `List`, `Input`, `Select`                                                          |\n",{"name":5,"description":7},"master","cbded6c96796a063405af105d5b3209ab6219407","dotfiles\u002Fdot_agents\u002Fskills\u002Fpi-extension-builder",0,"https:\u002F\u002Fgithub.com\u002FArtawower\u002Fkaizen","https:\u002F\u002Fgithub.com\u002FArtawower","workationmode.com","2026-11-10 19:23:03",{"source":8,"skillName":5,"commands":53,"prompt":63,"zipAvailable":64},[54,57,60],{"tool":55,"command":56},"npx","npx skills add Artawower\u002Fkaizen --skill pi-extension-builder",{"tool":58,"command":59},"bunx","bunx skills add Artawower\u002Fkaizen --skill pi-extension-builder",{"tool":61,"command":62},"pnpm","pnpm dlx skills add Artawower\u002Fkaizen --skill pi-extension-builder","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FArtawower\u002Fkaizen\u002Fblob\u002Fmaster\u002Fdotfiles\u002Fdot_agents\u002Fskills\u002Fpi-extension-builder\u002FSKILL.md",true,[],[67,99,117,141,160,185],{"skillNo":68,"name":69,"nameZh":6,"description":70,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":71,"categories":72,"keywords":78,"publishedAt":39},"01M71SYJ1B45ZKM8J96AZ3TS0H","yt-analyze","Fetch YouTrack task + comments via MCP, critically analyze relevance and requirements, produce concise summary of what to implement, and build an implementation plan mapped to codebase. Trigger - YouTrack issue ID or request to \"analyze task\", \"plan task\", \"break down YT issue\".","https:\u002F\u002Fgithub.com\u002FArtawower\u002Fkaizen\u002Fblob\u002Fmaster\u002Fdotfiles\u002Fdot_agents\u002Fskills\u002Fyt-analyze\u002FSKILL.md",[73],{"categoryNo":74,"categoryName":75,"taxonomyType":76,"taxonomyTypeDesc":77},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98],"analyze","yt analyze","yt","fetch","implementation plan","MCP","plan task","plan","request","break","issue","youtrack","down","trigger","produce","break down","comments","requirements","implement","task",{"skillNo":100,"name":101,"nameZh":6,"description":102,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":103,"categories":104,"keywords":105,"publishedAt":39},"01M71SYF7RSTEXKDWPXJ08EVQG","youtrack-task","Analyzes a YouTrack issue, reviews comments and attachments, and proposes or creates actionable subtasks. Use when the user gives a YouTrack issue ID and wants synthesis, decomposition, or follow-up tasks.","https:\u002F\u002Fgithub.com\u002FArtawower\u002Fkaizen\u002Fblob\u002Fmaster\u002Fdotfiles\u002Fdot_agents\u002Fskills\u002Fyoutrack-task\u002FSKILL.md",[],[106,90,98,107,108,109,110,111,112,89,113,31,29,95,114,115,116],"youtrack task","id","reviews","attachments","decomposition","actionable","up","follow-up","tasks","Synthesis","user",{"skillNo":118,"name":119,"nameZh":6,"description":120,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":121,"categories":122,"keywords":123,"publishedAt":39},"01M71SYCE94601T6DA5G2GDKYA","youtrack-search","Searches YouTrack from natural language or native query syntax and returns a concise report with the most relevant issues. Use when the user wants to find issues, triage work, or translate a plain-language query into YouTrack search.","https:\u002F\u002Fgithub.com\u002FArtawower\u002Fkaizen\u002Fblob\u002Fmaster\u002Fdotfiles\u002Fdot_agents\u002Fskills\u002Fyoutrack-search\u002FSKILL.md",[],[124,125,90,126,127,128,129,130,31,29,131,132,133,134,135,136,137,138,139,140],"search","youtrack search","natural language","relevant","translate","issues","plain-language","query","with","work","concise","native","find","report","syntax","triage","plain",{"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":6,"sourceHtmlUrl":145,"categories":146,"keywords":155,"publishedAt":39},"01M71SYAXN8EA6DDXEZWVY872S","writing-for-agents","Writing documents for agents. Use when creating or editing skills, or modifying AGENTS.md or CLAUDE.md.","https:\u002F\u002Fgithub.com\u002FArtawower\u002Fkaizen\u002Fblob\u002Fmaster\u002Fdotfiles\u002Fdot_agents\u002Fskills\u002Fwriting-for-agents\u002FSKILL.md",[147,150],{"categoryNo":148,"categoryName":149,"taxonomyType":76,"taxonomyTypeDesc":77},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":151,"categoryName":152,"taxonomyType":153,"taxonomyTypeDesc":154},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[156,36,157,158,31,159,29],"writing for agents","writing","editing","documents",{"skillNo":161,"name":162,"nameZh":6,"description":163,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":164,"categories":165,"keywords":169,"publishedAt":39},"01M71SY8ZKMWPF8ZAENT7MQE28","write-a-prd","Create a PRD through user interview, codebase exploration, and module design, then submit as a GitHub issue. Use when user wants to write a PRD, create a product requirements document, or plan a new feature.","https:\u002F\u002Fgithub.com\u002FArtawower\u002Fkaizen\u002Fblob\u002Fmaster\u002Fdotfiles\u002Fdot_agents\u002Fskills\u002Fwrite-a-prd\u002FSKILL.md",[166],{"categoryNo":167,"categoryName":168,"taxonomyType":153,"taxonomyTypeDesc":154},"01JBSEEDCAT000000000000031","产品经理",[170,171,172,173,174,175,176,177,178,179,180,31,181,29,182,183,96,27,184,86],"write","write a prd","prd","interview","as","exploration","feature","submit","design","module","new","document","user interview","codebase exploration","new feature",{"skillNo":186,"name":187,"nameZh":6,"description":188,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":189,"categories":190,"keywords":191,"publishedAt":39},"01M71SY6J9F119TJSMA2YBEP5P","vitest","Plan and write Vitest tests for changed code. Analyses git diff, checks existing tests, produces a concrete test plan using flat test structure (no describe\u002Fit blocks). Use when adding tests for new\u002Fchanged code, improving Vitest coverage, or asking what to test after a change.","https:\u002F\u002Fgithub.com\u002FArtawower\u002Fkaizen\u002Fblob\u002Fmaster\u002Fdotfiles\u002Fdot_agents\u002Fskills\u002Fvitest\u002FSKILL.md",[],[187,192,193,194,36,195,180,31,196,197,29,198,199,200,86,201,202,170,203,204],"coverage","test plan","diff","tests","Existing","adding tests","code","test","structure","change","flat","blocks","git"]