claude-code-session-manager 0.92.1 → 0.94.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/dist/assets/DataModel-B0LDnnSL.js +1 -0
  2. package/dist/assets/{History-BOR_fJNr.js → History-C685Kytt.js} +2 -2
  3. package/dist/assets/{Hooks-BtD436iL.js → Hooks-CwLnp0Z_.js} +3 -3
  4. package/dist/assets/HostBilko-CwEHEKYk.js +1 -0
  5. package/dist/assets/{Library-DeKdY-tD.js → Library-BU9np05E.js} +25 -25
  6. package/dist/assets/{MarkdownEditor-CbzC-Oqf.js → MarkdownEditor-B74ogK2f.js} +1 -1
  7. package/dist/assets/McpServers-BLM3ftzP.js +2 -0
  8. package/dist/assets/{Memory-B68AJjg2.js → Memory-DAP1t8bA.js} +6 -6
  9. package/dist/assets/{Permissions-Cr0RRvNy.js → Permissions-3pGLJmxQ.js} +3 -3
  10. package/dist/assets/Plugins-Q1KoLEzn.js +2 -0
  11. package/dist/assets/ProvenanceBadge-BnjBQiV9.js +1 -0
  12. package/dist/assets/{SaveBar-87ZJfscX.js → SaveBar-Zq2NfcPf.js} +1 -1
  13. package/dist/assets/Scheduler-D488ebKm.js +16 -0
  14. package/dist/assets/{ScopeSwitcher-CKzpqjJ_.js → ScopeSwitcher-Cnojv22D.js} +1 -1
  15. package/dist/assets/Settings-D5Lhj7ga.js +3 -0
  16. package/dist/assets/{SkillReferenceGraph-D_-wg4r9.js → SkillReferenceGraph-BRDiE6Hv.js} +2 -2
  17. package/dist/assets/Skills-BQDqp-EN.js +3 -0
  18. package/dist/assets/SystemPrompt-tFr19Od6.js +1 -0
  19. package/dist/assets/TagLibrary-BjyrnaRE.js +1 -0
  20. package/dist/assets/{TiptapBody-DYXIp8aG.js → TiptapBody-DGzSg3BO.js} +1 -1
  21. package/dist/assets/{Toggle-CDXR5l3m.js → Toggle-DzoROibf.js} +1 -1
  22. package/dist/assets/index-CCl4tz-u.js +3079 -0
  23. package/dist/assets/{index-D3P_jldk.css → index-CKH5Uxik.css} +1 -1
  24. package/dist/assets/settingsSchema-BYKVe1WM.js +1 -0
  25. package/dist/index.html +2 -2
  26. package/package.json +6 -3
  27. package/scripts/README.md +3 -0
  28. package/src/main/__tests__/agentEffortResolve.test.cjs +117 -0
  29. package/src/main/__tests__/agentLibrary.test.cjs +21 -0
  30. package/src/main/__tests__/agentModelResolve.test.cjs +16 -0
  31. package/src/main/__tests__/agentOverlayWrite.test.cjs +95 -0
  32. package/src/main/__tests__/chat-cancel-terminal.test.cjs +5 -2
  33. package/src/main/__tests__/chat-exit-close-race.test.cjs +8 -2
  34. package/src/main/__tests__/chat-mcp-consent-notice.test.cjs +5 -2
  35. package/src/main/__tests__/chatRunner-session-flag-retry.test.cjs +44 -0
  36. package/src/main/__tests__/intradayRefresh.test.cjs +39 -0
  37. package/src/main/__tests__/openExternalApp-spawn-error.test.cjs +25 -0
  38. package/src/main/__tests__/opsErrorLog.test.cjs +22 -0
  39. package/src/main/__tests__/personaMerge.test.cjs +169 -0
  40. package/src/main/__tests__/prdCreatePlanId.test.cjs +132 -0
  41. package/src/main/__tests__/promptSessionsCreateEpicHandler.test.cjs +13 -0
  42. package/src/main/__tests__/pty-epic-worktree-spawn-cwd.test.cjs +21 -0
  43. package/src/main/__tests__/rateLimitPollerStreak.test.cjs +14 -0
  44. package/src/main/__tests__/runVerify-atomic-verdicts.test.cjs +26 -0
  45. package/src/main/__tests__/runVerify-landed-commit-outranks.test.cjs +11 -1
  46. package/src/main/__tests__/runVerify-transcript-commit-evidence.test.cjs +11 -1
  47. package/src/main/__tests__/runVerify.test.cjs +12 -1
  48. package/src/main/__tests__/scheduler-prd-persona-spawn.test.cjs +47 -2
  49. package/src/main/__tests__/transcriptsUsageFor.test.cjs +112 -1
  50. package/src/main/agentLibrary.cjs +86 -40
  51. package/src/main/build-info.json +4 -4
  52. package/src/main/chatRunner.cjs +50 -10
  53. package/src/main/git.cjs +9 -2
  54. package/src/main/historyAggregator.cjs +2 -19
  55. package/src/main/index.cjs +17 -8
  56. package/src/main/ipcSchemas.cjs +25 -3
  57. package/src/main/lib/__tests__/childWithLog.test.cjs +180 -0
  58. package/src/main/lib/__tests__/delegationReadiness.test.cjs +19 -0
  59. package/src/main/lib/__tests__/effectiveModelInfo.test.cjs +10 -5
  60. package/src/main/lib/__tests__/gitCacheBound.test.cjs +69 -0
  61. package/src/main/lib/__tests__/modelCatalog.test.cjs +202 -0
  62. package/src/main/lib/agentEffortResolve.cjs +74 -0
  63. package/src/main/lib/agentModelResolve.cjs +52 -59
  64. package/src/main/lib/agentPersonaSchema.cjs +5 -0
  65. package/src/main/lib/childWithLog.cjs +92 -51
  66. package/src/main/lib/delegationReadiness.cjs +3 -1
  67. package/src/main/lib/effectiveModelInfo.cjs +38 -20
  68. package/src/main/lib/epicMint.cjs +5 -2
  69. package/src/main/lib/epicSpawnPlan.cjs +27 -8
  70. package/src/main/lib/epicTranscriptPath.cjs +5 -1
  71. package/src/main/lib/epicWorktreeMerge.cjs +7 -6
  72. package/src/main/lib/headTailBuffer.cjs +43 -0
  73. package/src/main/lib/intradayRefresh.cjs +33 -0
  74. package/src/main/lib/lruCache.cjs +39 -0
  75. package/src/main/lib/modelCatalog.cjs +243 -0
  76. package/src/main/lib/openExternalApp.cjs +27 -9
  77. package/src/main/lib/opsErrorLog.cjs +22 -0
  78. package/src/main/lib/personaMerge.cjs +166 -0
  79. package/src/main/lib/prdCreate.cjs +23 -5
  80. package/src/main/lib/prdDisposition.cjs +46 -0
  81. package/src/main/lib/prdFrontmatter.cjs +6 -2
  82. package/src/main/lib/promptSessionSchema.cjs +5 -0
  83. package/src/main/lib/promptSessionsCreateEpic.cjs +5 -3
  84. package/src/main/lib/rendererRecovery.cjs +141 -0
  85. package/src/main/lib/scheduleJobSchema.cjs +3 -0
  86. package/src/main/runVerify.cjs +3 -1
  87. package/src/main/scheduler/prdParser.cjs +2 -0
  88. package/src/main/scheduler.cjs +381 -262
  89. package/src/main/templates/PRD_AUTHORING.md +4 -0
  90. package/src/main/transcripts.cjs +54 -11
  91. package/src/preload/api.d.ts +56 -3
  92. package/src/preload/index.cjs +4 -0
  93. package/dist/assets/AgentLibrary-Ci6u03bq.js +0 -3
  94. package/dist/assets/DataModel-BIqcjsv2.js +0 -1
  95. package/dist/assets/HostBilko-CMe5cH3H.js +0 -1
  96. package/dist/assets/ListDetail-CtVjrHKB.js +0 -1
  97. package/dist/assets/McpServers-DKN75Shn.js +0 -2
  98. package/dist/assets/Panel-C2YTW-qP.js +0 -1
  99. package/dist/assets/Plugins-DbZkJs5l.js +0 -2
  100. package/dist/assets/ProvenanceBadge-kJ__BOQv.js +0 -1
  101. package/dist/assets/Scheduler-DdEaxku8.js +0 -16
  102. package/dist/assets/Settings-CjywVsNB.js +0 -3
  103. package/dist/assets/Skills-Cd_yPO_l.js +0 -3
  104. package/dist/assets/SystemPrompt-2z6eGPSF.js +0 -1
  105. package/dist/assets/TagLibrary-DcaWQSp4.js +0 -1
  106. package/dist/assets/index-D5H_H5wC.js +0 -3074
  107. package/dist/assets/settingsSchema-JRDfjgHb.js +0 -3
@@ -1,46 +1,46 @@
1
- import{aN as D,au as m,ah as e,l as P,b as j,aH as T}from"./index-D5H_H5wC.js";const G=[{id:"filesystem",name:"Filesystem",description:"Secure file operations with configurable access controls",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem",config:{command:"npx",args:["-y","@modelcontextprotocol/server-filesystem","<path>"]},envVars:[]},{id:"fetch",name:"Fetch",description:"Web content fetching and conversion for efficient LLM usage",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/fetch",config:{command:"uvx",args:["mcp-server-fetch"]},envVars:[]},{id:"memory",name:"Memory",description:"Knowledge graph-based persistent memory system",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/memory",config:{command:"npx",args:["-y","@modelcontextprotocol/server-memory"]},envVars:[]},{id:"sequential-thinking",name:"Sequential Thinking",description:"Dynamic and reflective problem-solving through thought sequences",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/sequentialthinking",config:{command:"npx",args:["-y","@modelcontextprotocol/server-sequential-thinking"]},envVars:[]},{id:"git",name:"Git",description:"Tools to read, search, and manipulate Git repositories",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/git",config:{command:"uvx",args:["mcp-server-git","--repository","<path>"]},envVars:[]},{id:"time",name:"Time",description:"Time and timezone conversion capabilities",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/time",config:{command:"uvx",args:["mcp-server-time"]},envVars:[]},{id:"everything",name:"Everything",description:"Reference/test server with prompts, resources, and tools",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/everything",config:{command:"npx",args:["-y","@modelcontextprotocol/server-everything"]},envVars:[]},{id:"github",name:"GitHub",description:"Official GitHub repository, issues, and PR management",official:!1,homepage:"https://github.com/github/github-mcp-server",config:{command:"docker",args:["run","-i","--rm","-e","GITHUB_PERSONAL_ACCESS_TOKEN","ghcr.io/github/github-mcp-server"]},envVars:["GITHUB_PERSONAL_ACCESS_TOKEN"]},{id:"gitlab",name:"GitLab",description:"GitLab API integration for projects, issues, and merge requests",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/gitlab",config:{command:"npx",args:["-y","@modelcontextprotocol/server-gitlab"]},envVars:["GITLAB_PERSONAL_ACCESS_TOKEN","GITLAB_API_URL"]},{id:"postgres",name:"PostgreSQL",description:"Read-only database access with schema inspection",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/postgres",config:{command:"npx",args:["-y","@modelcontextprotocol/server-postgres","<connection-string>"]},envVars:[]},{id:"sqlite",name:"SQLite",description:"Database interaction and business intelligence over SQLite",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/sqlite",config:{command:"uvx",args:["mcp-server-sqlite","--db-path","<path>"]},envVars:[]},{id:"slack",name:"Slack",description:"Channel management and messaging for Slack workspaces",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/slack",config:{command:"npx",args:["-y","@modelcontextprotocol/server-slack"]},envVars:["SLACK_BOT_TOKEN","SLACK_TEAM_ID"]},{id:"google-drive",name:"Google Drive",description:"File access and search for Google Drive",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/gdrive",config:{command:"npx",args:["-y","@modelcontextprotocol/server-gdrive"]},envVars:["GDRIVE_CREDENTIALS_PATH"]},{id:"google-maps",name:"Google Maps",description:"Location services, directions, and place details",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/google-maps",config:{command:"npx",args:["-y","@modelcontextprotocol/server-google-maps"]},envVars:["GOOGLE_MAPS_API_KEY"]},{id:"puppeteer",name:"Puppeteer",description:"Browser automation and web scraping via Puppeteer",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/puppeteer",config:{command:"npx",args:["-y","@modelcontextprotocol/server-puppeteer"]},envVars:[]},{id:"playwright",name:"Playwright",description:"Cross-browser automation for navigation, screenshots, and data extraction",official:!1,homepage:"https://github.com/microsoft/playwright-mcp",config:{command:"npx",args:["-y","@playwright/mcp@latest"]},envVars:[]},{id:"brave-search",name:"Brave Search",description:"Web and local search using the Brave Search API",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/brave-search",config:{command:"npx",args:["-y","@modelcontextprotocol/server-brave-search"]},envVars:["BRAVE_API_KEY"]},{id:"redis",name:"Redis",description:"Interact with Redis key-value stores",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/redis",config:{command:"npx",args:["-y","@modelcontextprotocol/server-redis","<redis-url>"]},envVars:[]},{id:"sentry",name:"Sentry",description:"Retrieve and analyze Sentry error tracking issues",official:!1,homepage:"https://github.com/getsentry/sentry-mcp",config:{command:"npx",args:["-y","@sentry/mcp-server@latest"]},envVars:["SENTRY_AUTH_TOKEN"]},{id:"linear",name:"Linear",description:"Issue tracking and project management for Linear",official:!1,homepage:"https://linear.app/docs/mcp",config:{command:"npx",args:["-y","mcp-remote","https://mcp.linear.app/sse"]},envVars:[]},{id:"notion",name:"Notion",description:"Notion workspace page and database management",official:!1,homepage:"https://github.com/makenotion/notion-mcp-server",config:{command:"npx",args:["-y","@notionhq/notion-mcp-server"]},envVars:["NOTION_API_KEY"]},{id:"stripe",name:"Stripe",description:"Payment processing, customers, and invoices via Stripe API",official:!1,homepage:"https://github.com/stripe/agent-toolkit",config:{command:"npx",args:["-y","@stripe/mcp","--tools=all"]},envVars:["STRIPE_SECRET_KEY"]},{id:"cloudflare",name:"Cloudflare",description:"Manage Cloudflare Workers, KV, R2, D1, and Workers AI",official:!1,homepage:"https://github.com/cloudflare/mcp-server-cloudflare",config:{command:"npx",args:["-y","mcp-remote","https://observability.mcp.cloudflare.com/sse"]},envVars:[]},{id:"context7",name:"Context7",description:"Up-to-date version-specific library docs injected into prompts",official:!1,homepage:"https://github.com/upstash/context7",config:{command:"npx",args:["-y","@upstash/context7-mcp@latest"]},envVars:[]},{id:"tavily",name:"Tavily",description:"AI-optimized web search with clean structured results",official:!1,homepage:"https://github.com/tavily-ai/tavily-mcp",config:{command:"npx",args:["-y","tavily-mcp@latest"]},envVars:["TAVILY_API_KEY"]},{id:"perplexity",name:"Perplexity",description:"Answer-engine search with deep research and reasoning",official:!1,homepage:"https://github.com/ppl-ai/modelcontextprotocol",config:{command:"npx",args:["-y","server-perplexity-ask"]},envVars:["PERPLEXITY_API_KEY"]},{id:"figma",name:"Figma Dev Mode",description:"First-party Figma design-to-code bridge exposing node tree",official:!1,homepage:"https://help.figma.com/hc/en-us/articles/32132100833559",config:{url:"http://127.0.0.1:3845/sse"},envVars:[]},{id:"supabase",name:"Supabase",description:"Manage Supabase projects, tables, and SQL queries",official:!1,homepage:"https://github.com/supabase-community/supabase-mcp",config:{command:"npx",args:["-y","@supabase/mcp-server-supabase@latest"]},envVars:["SUPABASE_ACCESS_TOKEN"]},{id:"atlassian",name:"Atlassian (Jira/Confluence)",description:"Official Jira and Confluence integration",official:!1,homepage:"https://www.atlassian.com/platform/remote-mcp-server",config:{command:"npx",args:["-y","mcp-remote","https://mcp.atlassian.com/v1/sse"]},envVars:[]},{id:"aws",name:"AWS",description:"AWS services access and best-practice guidance",official:!1,homepage:"https://github.com/awslabs/mcp",config:{command:"uvx",args:["awslabs.core-mcp-server@latest"]},envVars:["AWS_PROFILE","AWS_REGION"]},{id:"obsidian",name:"Obsidian",description:"Read and search notes in an Obsidian vault",official:!1,homepage:"https://github.com/MarkusPfundstein/mcp-obsidian",config:{command:"uvx",args:["mcp-obsidian"]},envVars:["OBSIDIAN_API_KEY"]}],q=[{id:"pdf",name:"PDF",description:"Create, edit, and extract content from PDF documents",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/pdf"},{id:"docx",name:"DOCX",description:"Create and edit Microsoft Word documents",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/docx"},{id:"xlsx",name:"XLSX",description:"Create and edit Excel spreadsheets with formulas and formatting",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/xlsx"},{id:"pptx",name:"PPTX",description:"Create and edit PowerPoint presentations",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/pptx"},{id:"webapp-testing",name:"Webapp Testing",description:"Test web applications using Playwright-driven browser automation",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/webapp-testing"},{id:"playwright-e2e",name:"Playwright E2E",description:"End-to-end browser tests — navigation, forms, assertions, waiting strategies",official:!1,source:"local"},{id:"playwright-visual-testing",name:"Playwright Visual Testing",description:"Visual regression testing — screenshot comparison, pixel diffs, responsive layouts",official:!1,source:"local"},{id:"playwright-accessibility",name:"Playwright Accessibility",description:"Accessibility testing — WCAG compliance, axe-core scans, keyboard navigation",official:!1,source:"local"},{id:"playwright-api-testing",name:"Playwright API Testing",description:"API testing with Playwright request context — REST endpoints, auth flows, contracts",official:!1,source:"local"},{id:"playwright-debug",name:"Playwright Debug",description:"Debug failing tests — trace viewer, inspector, headed mode, flaky test fixes",official:!1,source:"local"},{id:"web-artifacts-builder",name:"Web Artifacts Builder",description:"Build polished interactive web artifacts and demos",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/web-artifacts-builder"},{id:"frontend-design",name:"Frontend Design",description:"Apply frontend UI/UX design patterns and visual polish",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/frontend-design"},{id:"canvas-design",name:"Canvas Design",description:"Canvas-based graphic design and composition techniques",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/canvas-design"},{id:"algorithmic-art",name:"Algorithmic Art",description:"Create generative and algorithmic art",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/algorithmic-art"},{id:"brand-guidelines",name:"Brand Guidelines",description:"Apply brand identity and style guideline specifications",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/brand-guidelines"},{id:"theme-factory",name:"Theme Factory",description:"Generate and customize visual themes",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/theme-factory"},{id:"slack-gif-creator",name:"Slack GIF Creator",description:"Create animated GIFs suitable for Slack",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/slack-gif-creator"},{id:"doc-coauthoring",name:"Doc Coauthoring",description:"Collaborative document authoring and editing workflows",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/doc-coauthoring"},{id:"internal-comms",name:"Internal Comms",description:"Internal communications templates and drafting",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/internal-comms"},{id:"claude-api",name:"Claude API",description:"Build apps with the Claude API and Anthropic SDKs",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/claude-api"},{id:"mcp-builder",name:"MCP Builder",description:"Scaffold and build new Model Context Protocol servers",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/mcp-builder"},{id:"skill-creator",name:"Skill Creator",description:"Scaffold and create new Claude Code skills",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/skill-creator"}],M=[{id:"session-manager-dev",name:"Session Manager Dev",description:"Default end-to-end dev skillset: /develop + /prd (decompose → scheduler PRDs), /process-feedback + /my-feedback (cross-project intake), /project-status + /optimize-kpi + /local-project-health (status & KPI loop), /requesting-code-review + /security-review (review gate), /explain-to-me (HUMAN_LEARN docs).",official:!1,source:"https://github.com/StanislavBG/claude-code-session-manager/tree/main/plugins/session-manager-dev",bundles:["skills"],marketplace:{add:"bundled",name:"session-manager"}},{id:"code-review",name:"Code Review",description:"Comprehensive code review with best practices and improvement suggestions",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/code-review",bundles:["commands","agents"]},{id:"pr-review-toolkit",name:"PR Review Toolkit",description:"Pull request review automation and workflows",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/pr-review-toolkit",bundles:["commands","agents"]},{id:"commit-commands",name:"Commit Commands",description:"Git commit workflow shortcuts with conventional commit formatting",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/commit-commands",bundles:["commands"]},{id:"feature-dev",name:"Feature Dev",description:"Feature development assistance from spec to implementation",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/feature-dev",bundles:["commands","agents"]},{id:"security-guidance",name:"Security Guidance",description:"Security best-practice review and enforcement",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/security-guidance",bundles:["commands","agents"]},{id:"agent-sdk-dev",name:"Agent SDK Dev",description:"Development tools for building with the Claude Agent SDK",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/agent-sdk-dev",bundles:["commands","skills"]},{id:"plugin-dev",name:"Plugin Dev",description:"Scaffolding and tooling for authoring Claude Code plugins",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/plugin-dev",bundles:["commands","skills"]},{id:"mcp-server-dev",name:"MCP Server Dev",description:"Develop and test Model Context Protocol servers",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev",bundles:["commands","skills"]},{id:"skill-creator",name:"Skill Creator",description:"Framework for creating and iterating on new skills",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/skill-creator",bundles:["commands","skills"]},{id:"claude-md-management",name:"CLAUDE.md Management",description:"Manage and maintain CLAUDE.md project memory files",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/claude-md-management",bundles:["commands"]},{id:"typescript-lsp",name:"TypeScript LSP",description:"TypeScript/JavaScript language server integration",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/typescript-lsp",bundles:["hooks","commands"]},{id:"pyright-lsp",name:"Pyright LSP",description:"Python language server integration via Pyright",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/pyright-lsp",bundles:["hooks","commands"]},{id:"rust-analyzer-lsp",name:"Rust Analyzer LSP",description:"Rust language server integration via rust-analyzer",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/rust-analyzer-lsp",bundles:["hooks","commands"]},{id:"gopls-lsp",name:"Go LSP (gopls)",description:"Go language server integration via gopls",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/gopls-lsp",bundles:["hooks","commands"]},{id:"code-simplifier",name:"Code Simplifier",description:"Review changed code for reuse, quality, and efficiency then fix issues",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/code-simplifier",bundles:["commands","agents"]},{id:"hookify",name:"Hookify",description:"Utilities and templates for authoring Claude Code hooks",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/hookify",bundles:["commands","skills"]},{id:"frontend-design-plugin",name:"Frontend Design Plugin",description:"Frontend design assistance and visual polish workflows",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/frontend-design",bundles:["commands","skills","agents"]},{id:"clangd-lsp",name:"clangd-lsp",description:"C/C++ diagnostics via clangd. Requires clangd on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/clangd-lsp",bundles:["hooks","commands"]},{id:"csharp-lsp",name:"csharp-lsp",description:"C# diagnostics. Requires OmniSharp or Roslyn LSP on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/csharp-lsp",bundles:["hooks","commands"]},{id:"jdtls-lsp",name:"jdtls-lsp",description:"Java diagnostics via Eclipse JDT LS. Requires jdtls on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/jdtls-lsp",bundles:["hooks","commands"]},{id:"kotlin-lsp",name:"kotlin-lsp",description:"Kotlin diagnostics. Requires kotlin-language-server on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/kotlin-lsp",bundles:["hooks","commands"]},{id:"lua-lsp",name:"lua-lsp",description:"Lua diagnostics. Requires lua-language-server on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/lua-lsp",bundles:["hooks","commands"]},{id:"php-lsp",name:"php-lsp",description:"PHP diagnostics. Requires intelephense or phpactor on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/php-lsp",bundles:["hooks","commands"]},{id:"swift-lsp",name:"swift-lsp",description:"Swift diagnostics via sourcekit-lsp. Requires sourcekit-lsp on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/swift-lsp",bundles:["hooks","commands"]},{id:"github",name:"github",description:"GitHub PRs, issues, gh-style flows.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/github",bundles:["mcp"]},{id:"gitlab",name:"gitlab",description:"GitLab MRs, issues, pipelines.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/gitlab",bundles:["mcp"]},{id:"atlassian",name:"atlassian",description:"Jira / Confluence search and updates.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/atlassian",bundles:["mcp"]},{id:"asana",name:"asana",description:"Asana task and project ops.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/asana",bundles:["mcp"]},{id:"linear",name:"linear",description:"Linear issue tracking — pairs with the Tasks tab.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/linear",bundles:["mcp"]},{id:"notion",name:"notion",description:"Notion document lookup and edits.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/notion",bundles:["mcp"]},{id:"figma",name:"figma",description:"Figma file inspection for UI work.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/figma",bundles:["mcp"]},{id:"vercel",name:"vercel",description:"Vercel deploy diagnostics.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/vercel",bundles:["mcp"]},{id:"firebase",name:"firebase",description:"Firebase project + Firestore ops.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/firebase",bundles:["mcp"]},{id:"supabase",name:"supabase",description:"Supabase database operations.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/supabase",bundles:["mcp"]},{id:"slack",name:"slack",description:"Slack DM / channel posting from agents.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/slack",bundles:["mcp"]},{id:"sentry",name:"sentry",description:"Sentry bug triage and event lookup.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/sentry",bundles:["mcp"]}],F=[{id:"prettier-on-write",name:"Prettier on Write",description:"Auto-format JS/TS/JSON/MD files after edit via prettier",event:"PostToolUse",matcher:"Write|Edit",command:"jq -r '.tool_input.file_path // empty' | grep -E '\\.(js|jsx|ts|tsx|json|md|css|html|yaml|yml)$' | xargs -r -I{} npx --no-install prettier --write {} 2>/dev/null || true"},{id:"black-on-write",name:"Black on Write (Python)",description:"Auto-format Python files after edit via black",event:"PostToolUse",matcher:"Write|Edit",command:"jq -r '.tool_input.file_path // empty' | grep -E '\\.py$' | xargs -r black -q 2>/dev/null || true"},{id:"rustfmt-on-write",name:"rustfmt on Write",description:"Auto-format Rust files after edit via rustfmt",event:"PostToolUse",matcher:"Write|Edit",command:"jq -r '.tool_input.file_path // empty' | grep -E '\\.rs$' | xargs -r rustfmt 2>/dev/null || true"},{id:"gofmt-on-write",name:"gofmt on Write",description:"Auto-format Go files after edit via gofmt",event:"PostToolUse",matcher:"Write|Edit",command:"jq -r '.tool_input.file_path // empty' | grep -E '\\.go$' | xargs -r gofmt -w 2>/dev/null || true"},{id:"block-secret-writes",name:"Block Writes to Secrets",description:"Deny edits to .env, credentials, key files",event:"PreToolUse",matcher:"Write|Edit",command:`path=$(jq -r '.tool_input.file_path // empty'); echo "$path" | grep -qE '(^|/)(\\.env|\\.env\\..+|id_rsa|id_ed25519|.*\\.pem|.*\\.key|credentials\\.json|\\.aws/credentials)$' && { echo '{"decision":"block","reason":"refusing to edit secret file"}'; exit 2; } || true`},{id:"notify-on-stop",name:"Desktop Notify on Stop",description:"Send a desktop notification when Claude finishes a turn",event:"Stop",command:`command -v notify-send >/dev/null && notify-send "Claude Code" "Session ready" || (command -v osascript >/dev/null && osascript -e 'display notification "Session ready" with title "Claude Code"') || true`},{id:"bell-on-notification",name:"Terminal Bell on Notification",description:"Ring the terminal bell on permission prompts / idle notifications",event:"Notification",command:"printf '\\a'"},{id:"log-tool-calls",name:"Log Tool Calls (JSONL)",description:"Append every tool call to ~/.claude/logs/tool-calls.jsonl for audit",event:"PreToolUse",command:"mkdir -p ~/.claude/logs && cat >> ~/.claude/logs/tool-calls.jsonl"},{id:"auto-stage-edits",name:"Auto-stage Edited Files",description:"git add each file Claude edits (inside a repo)",event:"PostToolUse",matcher:"Write|Edit",command:`path=$(jq -r '.tool_input.file_path // empty'); [ -n "$path" ] && git -C "$(dirname "$path")" add "$path" 2>/dev/null || true`},{id:"block-dangerous-bash",name:"Block Dangerous Bash",description:"Refuse rm -rf /, fork bombs, curl|sh pipes",event:"PreToolUse",matcher:"Bash",command:`cmd=$(jq -r '.tool_input.command // empty'); echo "$cmd" | grep -qE '(rm -rf /|:\\(\\)\\{.*\\};|curl.*\\|\\s*(bash|sh)|wget.*\\|\\s*(bash|sh)|mkfs\\.|dd if=.*of=/dev/)' && { echo '{"decision":"block","reason":"dangerous command pattern"}'; exit 2; } || true`},{id:"prepend-cwd-to-prompt",name:"Prepend CWD to Prompt",description:"Add cwd context to every user prompt automatically",event:"UserPromptSubmit",command:'echo "{\\"additionalContext\\":\\"cwd: $(pwd)\\"}"'},{id:"archive-transcript",name:"Archive Transcript on SessionEnd",description:"Copy the session jsonl to ~/.claude/archive/ when done",event:"SessionEnd",command:`src=$(jq -r '.transcript_path // empty'); [ -n "$src" ] && mkdir -p ~/.claude/archive && cp "$src" ~/.claude/archive/ 2>/dev/null || true`}],A=(t,o,l,n)=>`---
1
+ import{aS as D,az as g,ak as e,m as N,a as C,c as O,aL as T}from"./index-CCl4tz-u.js";const q=[{id:"filesystem",name:"Filesystem",description:"Secure file operations with configurable access controls",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem",config:{command:"npx",args:["-y","@modelcontextprotocol/server-filesystem","<path>"]},envVars:[]},{id:"fetch",name:"Fetch",description:"Web content fetching and conversion for efficient LLM usage",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/fetch",config:{command:"uvx",args:["mcp-server-fetch"]},envVars:[]},{id:"memory",name:"Memory",description:"Knowledge graph-based persistent memory system",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/memory",config:{command:"npx",args:["-y","@modelcontextprotocol/server-memory"]},envVars:[]},{id:"sequential-thinking",name:"Sequential Thinking",description:"Dynamic and reflective problem-solving through thought sequences",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/sequentialthinking",config:{command:"npx",args:["-y","@modelcontextprotocol/server-sequential-thinking"]},envVars:[]},{id:"git",name:"Git",description:"Tools to read, search, and manipulate Git repositories",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/git",config:{command:"uvx",args:["mcp-server-git","--repository","<path>"]},envVars:[]},{id:"time",name:"Time",description:"Time and timezone conversion capabilities",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/time",config:{command:"uvx",args:["mcp-server-time"]},envVars:[]},{id:"everything",name:"Everything",description:"Reference/test server with prompts, resources, and tools",official:!0,homepage:"https://github.com/modelcontextprotocol/servers/tree/main/src/everything",config:{command:"npx",args:["-y","@modelcontextprotocol/server-everything"]},envVars:[]},{id:"github",name:"GitHub",description:"Official GitHub repository, issues, and PR management",official:!1,homepage:"https://github.com/github/github-mcp-server",config:{command:"docker",args:["run","-i","--rm","-e","GITHUB_PERSONAL_ACCESS_TOKEN","ghcr.io/github/github-mcp-server"]},envVars:["GITHUB_PERSONAL_ACCESS_TOKEN"]},{id:"gitlab",name:"GitLab",description:"GitLab API integration for projects, issues, and merge requests",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/gitlab",config:{command:"npx",args:["-y","@modelcontextprotocol/server-gitlab"]},envVars:["GITLAB_PERSONAL_ACCESS_TOKEN","GITLAB_API_URL"]},{id:"postgres",name:"PostgreSQL",description:"Read-only database access with schema inspection",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/postgres",config:{command:"npx",args:["-y","@modelcontextprotocol/server-postgres","<connection-string>"]},envVars:[]},{id:"sqlite",name:"SQLite",description:"Database interaction and business intelligence over SQLite",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/sqlite",config:{command:"uvx",args:["mcp-server-sqlite","--db-path","<path>"]},envVars:[]},{id:"slack",name:"Slack",description:"Channel management and messaging for Slack workspaces",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/slack",config:{command:"npx",args:["-y","@modelcontextprotocol/server-slack"]},envVars:["SLACK_BOT_TOKEN","SLACK_TEAM_ID"]},{id:"google-drive",name:"Google Drive",description:"File access and search for Google Drive",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/gdrive",config:{command:"npx",args:["-y","@modelcontextprotocol/server-gdrive"]},envVars:["GDRIVE_CREDENTIALS_PATH"]},{id:"google-maps",name:"Google Maps",description:"Location services, directions, and place details",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/google-maps",config:{command:"npx",args:["-y","@modelcontextprotocol/server-google-maps"]},envVars:["GOOGLE_MAPS_API_KEY"]},{id:"puppeteer",name:"Puppeteer",description:"Browser automation and web scraping via Puppeteer",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/puppeteer",config:{command:"npx",args:["-y","@modelcontextprotocol/server-puppeteer"]},envVars:[]},{id:"playwright",name:"Playwright",description:"Cross-browser automation for navigation, screenshots, and data extraction",official:!1,homepage:"https://github.com/microsoft/playwright-mcp",config:{command:"npx",args:["-y","@playwright/mcp@latest"]},envVars:[]},{id:"brave-search",name:"Brave Search",description:"Web and local search using the Brave Search API",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/brave-search",config:{command:"npx",args:["-y","@modelcontextprotocol/server-brave-search"]},envVars:["BRAVE_API_KEY"]},{id:"redis",name:"Redis",description:"Interact with Redis key-value stores",official:!1,homepage:"https://github.com/modelcontextprotocol/servers-archived/tree/main/src/redis",config:{command:"npx",args:["-y","@modelcontextprotocol/server-redis","<redis-url>"]},envVars:[]},{id:"sentry",name:"Sentry",description:"Retrieve and analyze Sentry error tracking issues",official:!1,homepage:"https://github.com/getsentry/sentry-mcp",config:{command:"npx",args:["-y","@sentry/mcp-server@latest"]},envVars:["SENTRY_AUTH_TOKEN"]},{id:"linear",name:"Linear",description:"Issue tracking and project management for Linear",official:!1,homepage:"https://linear.app/docs/mcp",config:{command:"npx",args:["-y","mcp-remote","https://mcp.linear.app/sse"]},envVars:[]},{id:"notion",name:"Notion",description:"Notion workspace page and database management",official:!1,homepage:"https://github.com/makenotion/notion-mcp-server",config:{command:"npx",args:["-y","@notionhq/notion-mcp-server"]},envVars:["NOTION_API_KEY"]},{id:"stripe",name:"Stripe",description:"Payment processing, customers, and invoices via Stripe API",official:!1,homepage:"https://github.com/stripe/agent-toolkit",config:{command:"npx",args:["-y","@stripe/mcp","--tools=all"]},envVars:["STRIPE_SECRET_KEY"]},{id:"cloudflare",name:"Cloudflare",description:"Manage Cloudflare Workers, KV, R2, D1, and Workers AI",official:!1,homepage:"https://github.com/cloudflare/mcp-server-cloudflare",config:{command:"npx",args:["-y","mcp-remote","https://observability.mcp.cloudflare.com/sse"]},envVars:[]},{id:"context7",name:"Context7",description:"Up-to-date version-specific library docs injected into prompts",official:!1,homepage:"https://github.com/upstash/context7",config:{command:"npx",args:["-y","@upstash/context7-mcp@latest"]},envVars:[]},{id:"tavily",name:"Tavily",description:"AI-optimized web search with clean structured results",official:!1,homepage:"https://github.com/tavily-ai/tavily-mcp",config:{command:"npx",args:["-y","tavily-mcp@latest"]},envVars:["TAVILY_API_KEY"]},{id:"perplexity",name:"Perplexity",description:"Answer-engine search with deep research and reasoning",official:!1,homepage:"https://github.com/ppl-ai/modelcontextprotocol",config:{command:"npx",args:["-y","server-perplexity-ask"]},envVars:["PERPLEXITY_API_KEY"]},{id:"figma",name:"Figma Dev Mode",description:"First-party Figma design-to-code bridge exposing node tree",official:!1,homepage:"https://help.figma.com/hc/en-us/articles/32132100833559",config:{url:"http://127.0.0.1:3845/sse"},envVars:[]},{id:"supabase",name:"Supabase",description:"Manage Supabase projects, tables, and SQL queries",official:!1,homepage:"https://github.com/supabase-community/supabase-mcp",config:{command:"npx",args:["-y","@supabase/mcp-server-supabase@latest"]},envVars:["SUPABASE_ACCESS_TOKEN"]},{id:"atlassian",name:"Atlassian (Jira/Confluence)",description:"Official Jira and Confluence integration",official:!1,homepage:"https://www.atlassian.com/platform/remote-mcp-server",config:{command:"npx",args:["-y","mcp-remote","https://mcp.atlassian.com/v1/sse"]},envVars:[]},{id:"aws",name:"AWS",description:"AWS services access and best-practice guidance",official:!1,homepage:"https://github.com/awslabs/mcp",config:{command:"uvx",args:["awslabs.core-mcp-server@latest"]},envVars:["AWS_PROFILE","AWS_REGION"]},{id:"obsidian",name:"Obsidian",description:"Read and search notes in an Obsidian vault",official:!1,homepage:"https://github.com/MarkusPfundstein/mcp-obsidian",config:{command:"uvx",args:["mcp-obsidian"]},envVars:["OBSIDIAN_API_KEY"]}],M=[{id:"pdf",name:"PDF",description:"Create, edit, and extract content from PDF documents",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/pdf"},{id:"docx",name:"DOCX",description:"Create and edit Microsoft Word documents",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/docx"},{id:"xlsx",name:"XLSX",description:"Create and edit Excel spreadsheets with formulas and formatting",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/xlsx"},{id:"pptx",name:"PPTX",description:"Create and edit PowerPoint presentations",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/pptx"},{id:"webapp-testing",name:"Webapp Testing",description:"Test web applications using Playwright-driven browser automation",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/webapp-testing"},{id:"playwright-e2e",name:"Playwright E2E",description:"End-to-end browser tests — navigation, forms, assertions, waiting strategies",official:!1,source:"local"},{id:"playwright-visual-testing",name:"Playwright Visual Testing",description:"Visual regression testing — screenshot comparison, pixel diffs, responsive layouts",official:!1,source:"local"},{id:"playwright-accessibility",name:"Playwright Accessibility",description:"Accessibility testing — WCAG compliance, axe-core scans, keyboard navigation",official:!1,source:"local"},{id:"playwright-api-testing",name:"Playwright API Testing",description:"API testing with Playwright request context — REST endpoints, auth flows, contracts",official:!1,source:"local"},{id:"playwright-debug",name:"Playwright Debug",description:"Debug failing tests — trace viewer, inspector, headed mode, flaky test fixes",official:!1,source:"local"},{id:"web-artifacts-builder",name:"Web Artifacts Builder",description:"Build polished interactive web artifacts and demos",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/web-artifacts-builder"},{id:"frontend-design",name:"Frontend Design",description:"Apply frontend UI/UX design patterns and visual polish",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/frontend-design"},{id:"canvas-design",name:"Canvas Design",description:"Canvas-based graphic design and composition techniques",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/canvas-design"},{id:"algorithmic-art",name:"Algorithmic Art",description:"Create generative and algorithmic art",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/algorithmic-art"},{id:"brand-guidelines",name:"Brand Guidelines",description:"Apply brand identity and style guideline specifications",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/brand-guidelines"},{id:"theme-factory",name:"Theme Factory",description:"Generate and customize visual themes",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/theme-factory"},{id:"slack-gif-creator",name:"Slack GIF Creator",description:"Create animated GIFs suitable for Slack",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/slack-gif-creator"},{id:"doc-coauthoring",name:"Doc Coauthoring",description:"Collaborative document authoring and editing workflows",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/doc-coauthoring"},{id:"internal-comms",name:"Internal Comms",description:"Internal communications templates and drafting",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/internal-comms"},{id:"claude-api",name:"Claude API",description:"Build apps with the Claude API and Anthropic SDKs",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/claude-api"},{id:"mcp-builder",name:"MCP Builder",description:"Scaffold and build new Model Context Protocol servers",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/mcp-builder"},{id:"skill-creator",name:"Skill Creator",description:"Scaffold and create new Claude Code skills",official:!0,source:"https://github.com/anthropics/skills/tree/main/skills/skill-creator"}],F=[{id:"session-manager-dev",name:"Session Manager Dev",description:"Default end-to-end dev skillset: /develop + /prd (decompose → scheduler PRDs), /process-feedback + /my-feedback (cross-project intake), /project-status + /optimize-kpi + /local-project-health (status & KPI loop), /requesting-code-review + /security-review (review gate), /explain-to-me (HUMAN_LEARN docs).",official:!1,source:"https://github.com/StanislavBG/claude-code-session-manager/tree/main/plugins/session-manager-dev",bundles:["skills"],marketplace:{add:"bundled",name:"session-manager"}},{id:"code-review",name:"Code Review",description:"Comprehensive code review with best practices and improvement suggestions",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/code-review",bundles:["commands","agents"]},{id:"pr-review-toolkit",name:"PR Review Toolkit",description:"Pull request review automation and workflows",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/pr-review-toolkit",bundles:["commands","agents"]},{id:"commit-commands",name:"Commit Commands",description:"Git commit workflow shortcuts with conventional commit formatting",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/commit-commands",bundles:["commands"]},{id:"feature-dev",name:"Feature Dev",description:"Feature development assistance from spec to implementation",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/feature-dev",bundles:["commands","agents"]},{id:"security-guidance",name:"Security Guidance",description:"Security best-practice review and enforcement",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/security-guidance",bundles:["commands","agents"]},{id:"agent-sdk-dev",name:"Agent SDK Dev",description:"Development tools for building with the Claude Agent SDK",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/agent-sdk-dev",bundles:["commands","skills"]},{id:"plugin-dev",name:"Plugin Dev",description:"Scaffolding and tooling for authoring Claude Code plugins",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/plugin-dev",bundles:["commands","skills"]},{id:"mcp-server-dev",name:"MCP Server Dev",description:"Develop and test Model Context Protocol servers",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev",bundles:["commands","skills"]},{id:"skill-creator",name:"Skill Creator",description:"Framework for creating and iterating on new skills",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/skill-creator",bundles:["commands","skills"]},{id:"claude-md-management",name:"CLAUDE.md Management",description:"Manage and maintain CLAUDE.md project memory files",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/claude-md-management",bundles:["commands"]},{id:"typescript-lsp",name:"TypeScript LSP",description:"TypeScript/JavaScript language server integration",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/typescript-lsp",bundles:["hooks","commands"]},{id:"pyright-lsp",name:"Pyright LSP",description:"Python language server integration via Pyright",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/pyright-lsp",bundles:["hooks","commands"]},{id:"rust-analyzer-lsp",name:"Rust Analyzer LSP",description:"Rust language server integration via rust-analyzer",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/rust-analyzer-lsp",bundles:["hooks","commands"]},{id:"gopls-lsp",name:"Go LSP (gopls)",description:"Go language server integration via gopls",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/gopls-lsp",bundles:["hooks","commands"]},{id:"code-simplifier",name:"Code Simplifier",description:"Review changed code for reuse, quality, and efficiency then fix issues",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/code-simplifier",bundles:["commands","agents"]},{id:"hookify",name:"Hookify",description:"Utilities and templates for authoring Claude Code hooks",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/hookify",bundles:["commands","skills"]},{id:"frontend-design-plugin",name:"Frontend Design Plugin",description:"Frontend design assistance and visual polish workflows",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/frontend-design",bundles:["commands","skills","agents"]},{id:"clangd-lsp",name:"clangd-lsp",description:"C/C++ diagnostics via clangd. Requires clangd on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/clangd-lsp",bundles:["hooks","commands"]},{id:"csharp-lsp",name:"csharp-lsp",description:"C# diagnostics. Requires OmniSharp or Roslyn LSP on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/csharp-lsp",bundles:["hooks","commands"]},{id:"jdtls-lsp",name:"jdtls-lsp",description:"Java diagnostics via Eclipse JDT LS. Requires jdtls on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/jdtls-lsp",bundles:["hooks","commands"]},{id:"kotlin-lsp",name:"kotlin-lsp",description:"Kotlin diagnostics. Requires kotlin-language-server on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/kotlin-lsp",bundles:["hooks","commands"]},{id:"lua-lsp",name:"lua-lsp",description:"Lua diagnostics. Requires lua-language-server on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/lua-lsp",bundles:["hooks","commands"]},{id:"php-lsp",name:"php-lsp",description:"PHP diagnostics. Requires intelephense or phpactor on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/php-lsp",bundles:["hooks","commands"]},{id:"swift-lsp",name:"swift-lsp",description:"Swift diagnostics via sourcekit-lsp. Requires sourcekit-lsp on $PATH.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/swift-lsp",bundles:["hooks","commands"]},{id:"github",name:"github",description:"GitHub PRs, issues, gh-style flows.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/github",bundles:["mcp"]},{id:"gitlab",name:"gitlab",description:"GitLab MRs, issues, pipelines.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/gitlab",bundles:["mcp"]},{id:"atlassian",name:"atlassian",description:"Jira / Confluence search and updates.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/atlassian",bundles:["mcp"]},{id:"asana",name:"asana",description:"Asana task and project ops.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/asana",bundles:["mcp"]},{id:"linear",name:"linear",description:"Linear issue tracking — pairs with the Tasks tab.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/linear",bundles:["mcp"]},{id:"notion",name:"notion",description:"Notion document lookup and edits.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/notion",bundles:["mcp"]},{id:"figma",name:"figma",description:"Figma file inspection for UI work.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/figma",bundles:["mcp"]},{id:"vercel",name:"vercel",description:"Vercel deploy diagnostics.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/vercel",bundles:["mcp"]},{id:"firebase",name:"firebase",description:"Firebase project + Firestore ops.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/firebase",bundles:["mcp"]},{id:"supabase",name:"supabase",description:"Supabase database operations.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/supabase",bundles:["mcp"]},{id:"slack",name:"slack",description:"Slack DM / channel posting from agents.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/slack",bundles:["mcp"]},{id:"sentry",name:"sentry",description:"Sentry bug triage and event lookup.",official:!0,source:"https://github.com/anthropics/claude-plugins-official/tree/main/plugins/sentry",bundles:["mcp"]}],_=[{id:"prettier-on-write",name:"Prettier on Write",description:"Auto-format JS/TS/JSON/MD files after edit via prettier",event:"PostToolUse",matcher:"Write|Edit",command:"jq -r '.tool_input.file_path // empty' | grep -E '\\.(js|jsx|ts|tsx|json|md|css|html|yaml|yml)$' | xargs -r -I{} npx --no-install prettier --write {} 2>/dev/null || true"},{id:"black-on-write",name:"Black on Write (Python)",description:"Auto-format Python files after edit via black",event:"PostToolUse",matcher:"Write|Edit",command:"jq -r '.tool_input.file_path // empty' | grep -E '\\.py$' | xargs -r black -q 2>/dev/null || true"},{id:"rustfmt-on-write",name:"rustfmt on Write",description:"Auto-format Rust files after edit via rustfmt",event:"PostToolUse",matcher:"Write|Edit",command:"jq -r '.tool_input.file_path // empty' | grep -E '\\.rs$' | xargs -r rustfmt 2>/dev/null || true"},{id:"gofmt-on-write",name:"gofmt on Write",description:"Auto-format Go files after edit via gofmt",event:"PostToolUse",matcher:"Write|Edit",command:"jq -r '.tool_input.file_path // empty' | grep -E '\\.go$' | xargs -r gofmt -w 2>/dev/null || true"},{id:"block-secret-writes",name:"Block Writes to Secrets",description:"Deny edits to .env, credentials, key files",event:"PreToolUse",matcher:"Write|Edit",command:`path=$(jq -r '.tool_input.file_path // empty'); echo "$path" | grep -qE '(^|/)(\\.env|\\.env\\..+|id_rsa|id_ed25519|.*\\.pem|.*\\.key|credentials\\.json|\\.aws/credentials)$' && { echo '{"decision":"block","reason":"refusing to edit secret file"}'; exit 2; } || true`},{id:"notify-on-stop",name:"Desktop Notify on Stop",description:"Send a desktop notification when Claude finishes a turn",event:"Stop",command:`command -v notify-send >/dev/null && notify-send "Claude Code" "Session ready" || (command -v osascript >/dev/null && osascript -e 'display notification "Session ready" with title "Claude Code"') || true`},{id:"bell-on-notification",name:"Terminal Bell on Notification",description:"Ring the terminal bell on permission prompts / idle notifications",event:"Notification",command:"printf '\\a'"},{id:"log-tool-calls",name:"Log Tool Calls (JSONL)",description:"Append every tool call to ~/.claude/logs/tool-calls.jsonl for audit",event:"PreToolUse",command:"mkdir -p ~/.claude/logs && cat >> ~/.claude/logs/tool-calls.jsonl"},{id:"auto-stage-edits",name:"Auto-stage Edited Files",description:"git add each file Claude edits (inside a repo)",event:"PostToolUse",matcher:"Write|Edit",command:`path=$(jq -r '.tool_input.file_path // empty'); [ -n "$path" ] && git -C "$(dirname "$path")" add "$path" 2>/dev/null || true`},{id:"block-dangerous-bash",name:"Block Dangerous Bash",description:"Refuse rm -rf /, fork bombs, curl|sh pipes",event:"PreToolUse",matcher:"Bash",command:`cmd=$(jq -r '.tool_input.command // empty'); echo "$cmd" | grep -qE '(rm -rf /|:\\(\\)\\{.*\\};|curl.*\\|\\s*(bash|sh)|wget.*\\|\\s*(bash|sh)|mkfs\\.|dd if=.*of=/dev/)' && { echo '{"decision":"block","reason":"dangerous command pattern"}'; exit 2; } || true`},{id:"prepend-cwd-to-prompt",name:"Prepend CWD to Prompt",description:"Add cwd context to every user prompt automatically",event:"UserPromptSubmit",command:'echo "{\\"additionalContext\\":\\"cwd: $(pwd)\\"}"'},{id:"archive-transcript",name:"Archive Transcript on SessionEnd",description:"Copy the session jsonl to ~/.claude/archive/ when done",event:"SessionEnd",command:`src=$(jq -r '.transcript_path // empty'); [ -n "$src" ] && mkdir -p ~/.claude/archive && cp "$src" ~/.claude/archive/ 2>/dev/null || true`}],P=(t,n,r,s)=>`---
2
2
  name: ${t}
3
- description: ${o}
4
- tools: ${l}
3
+ description: ${n}
4
+ tools: ${r}
5
5
  ---
6
6
 
7
- ${n}
8
- `,ie=[{id:"code-reviewer",name:"Code Reviewer",description:"Review staged changes for bugs, style, and maintainability",tools:"Read, Grep, Glob, Bash",content:A("code-reviewer","Review staged changes for bugs, style, and maintainability","Read, Grep, Glob, Bash",`You are a senior code reviewer. Read the user's staged diff (via \`git diff --staged\`), walk each change, and report:
7
+ ${s}
8
+ `,le=[{id:"code-reviewer",name:"Code Reviewer",description:"Review staged changes for bugs, style, and maintainability",tools:"Read, Grep, Glob, Bash",content:P("code-reviewer","Review staged changes for bugs, style, and maintainability","Read, Grep, Glob, Bash",`You are a senior code reviewer. Read the user's staged diff (via \`git diff --staged\`), walk each change, and report:
9
9
  - correctness issues (bugs, edge cases, race conditions)
10
10
  - security issues (injection, auth, secrets)
11
11
  - maintainability issues (naming, duplication, abstractions)
12
12
  - style / convention deviations vs the rest of the repo
13
13
 
14
- Be specific: cite file:line. Distinguish blocking issues from nits. Do not rewrite — just review.`)},{id:"test-runner",name:"Test Runner",description:"Run the project test suite, report failures, suggest fixes",tools:"Bash, Read, Grep",content:A("test-runner","Run the project test suite, report failures, suggest fixes","Bash, Read, Grep","Detect the test framework (jest, vitest, pytest, cargo test, go test, …) from package manifests. Run the suite. For each failure: read the failing test + the code under test, diagnose the cause, and propose a concrete fix. Do not apply fixes yourself.")},{id:"security-auditor",name:"Security Auditor",description:"Scan code for common vulnerabilities and unsafe patterns",tools:"Read, Grep, Glob, Bash",content:A("security-auditor","Scan code for common vulnerabilities and unsafe patterns","Read, Grep, Glob, Bash","Audit the codebase for OWASP top-10 and common CWE patterns: SQL injection, XSS, SSRF, path traversal, hardcoded secrets, weak crypto, insecure deserialization, missing authz. Report findings with severity, file:line, and remediation sketch.")},{id:"docs-writer",name:"Docs Writer",description:"Generate or update docstrings and README sections",tools:"Read, Edit, Grep, Glob",content:A("docs-writer","Generate or update docstrings and README sections","Read, Edit, Grep, Glob","For each public symbol missing documentation, write a concise doc comment in the project's existing style. For README sections, match the existing tone. Never invent APIs — read the code first.")},{id:"refactorer",name:"Refactorer",description:"Propose structural refactors without changing behavior",tools:"Read, Grep, Glob, Edit",content:A("refactorer","Propose structural refactors without changing behavior","Read, Grep, Glob, Edit","Identify extract-method, extract-class, inline, rename, and dead-code opportunities. Prefer small reversible refactors. Always preserve behavior — no feature changes.")},{id:"debugger",name:"Debugger",description:"Diagnose a failing test or runtime error from a stack trace",tools:"Read, Grep, Glob, Bash",content:A("debugger","Diagnose a failing test or runtime error from a stack trace","Read, Grep, Glob, Bash","Given a stack trace or failing test, walk the call chain, read the relevant code, form a hypothesis, and propose a minimal fix. Reproduce the bug before fixing when possible.")},{id:"commit-msg-writer",name:"Commit Message Writer",description:"Write a conventional commit message from staged changes",tools:"Bash, Read",content:A("commit-msg-writer","Write a conventional commit message from staged changes","Bash, Read","Run `git diff --staged`, summarize the change, and produce a conventional-commit message: `<type>(<scope>): <subject>`. Types: feat, fix, refactor, docs, test, chore, perf. Subject ≤72 chars, imperative, lowercase.")},{id:"perf-profiler",name:"Performance Profiler",description:"Identify hot paths and perf regressions in changed code",tools:"Read, Grep, Glob, Bash",content:A("perf-profiler","Identify hot paths and perf regressions in changed code","Read, Grep, Glob, Bash","Look for accidental N+1 loops, quadratic scans, sync IO in hot loops, and unbounded allocations. Rank findings by likely impact; cite file:line. Do not micro-optimize without evidence.")},{id:"sql-reviewer",name:"SQL Reviewer",description:"Review SQL/ORM queries for correctness and performance",tools:"Read, Grep, Glob",content:A("sql-reviewer","Review SQL/ORM queries for correctness and performance","Read, Grep, Glob","Inspect SQL and ORM queries for missing indexes, SELECT *, N+1, cartesian joins, SQL injection risk, and transaction boundaries. Report severity + remediation.")},{id:"api-designer",name:"API Designer",description:"Review REST/GraphQL API design for consistency and correctness",tools:"Read, Grep, Glob",content:A("api-designer","Review REST/GraphQL API design for consistency and correctness","Read, Grep, Glob","Audit route naming, HTTP verb usage, status codes, pagination, auth, error envelopes, and versioning. Flag inconsistencies against the rest of the surface.")},{id:"migration-planner",name:"Migration Planner",description:"Draft a safe DB migration + rollback plan for a schema change",tools:"Read, Grep, Glob, Bash",content:A("migration-planner","Draft a safe DB migration + rollback plan for a schema change","Read, Grep, Glob, Bash","For the requested schema change, produce forward + rollback migrations, a backfill strategy for large tables, and a deploy sequence that keeps the old code running through the transition.")},{id:"dependency-auditor",name:"Dependency Auditor",description:"Audit dependencies for vulnerabilities and stale versions",tools:"Bash, Read",content:A("dependency-auditor","Audit dependencies for vulnerabilities and stale versions","Bash, Read","Run the ecosystem audit (npm audit, pip-audit, cargo audit, etc.) and read the lockfile. Rank CVEs by severity + reachability. Suggest upgrades with known-compatible versions.")}],O=[{id:"strict",name:"Strict",description:"Deny all network + dangerous bash; ask before edits; no auto-accept",permissions:{deny:["Bash(curl:*)","Bash(wget:*)","Bash(nc:*)","Bash(ssh:*)","Bash(rm -rf:*)","Bash(sudo:*)","WebFetch","WebSearch"],ask:["Edit","Write","Bash"],defaultMode:"default"}},{id:"standard-dev",name:"Standard Dev",description:"Allow common dev commands (git, npm, pnpm, cargo, go, make); deny destructive ops",permissions:{allow:["Bash(git:*)","Bash(npm:*)","Bash(pnpm:*)","Bash(yarn:*)","Bash(cargo:*)","Bash(go:*)","Bash(make:*)","Bash(ls:*)","Bash(pwd)","Bash(cat:*)","Bash(grep:*)","Bash(rg:*)","Bash(find:*)","Read","Glob","Grep"],deny:["Bash(rm -rf /:*)","Bash(sudo:*)","Bash(shutdown:*)","Bash(reboot:*)","Bash(dd:*)"],defaultMode:"acceptEdits"}},{id:"sandboxed",name:"Sandboxed",description:"Block writes outside cwd; allow reads everywhere; deny network and sudo",permissions:{deny:["Bash(sudo:*)","Bash(curl:*)","Bash(wget:*)","WebFetch","WebSearch"],ask:["Write","Edit"],defaultMode:"default",additionalDirectories:[]}},{id:"read-only",name:"Read-only",description:"Research / analysis only — no edits, no bash, no writes",permissions:{allow:["Read","Glob","Grep","WebFetch","WebSearch"],deny:["Write","Edit","Bash","NotebookEdit"],defaultMode:"default"}},{id:"plan-mode",name:"Plan Mode",description:"Force plan-mode by default; ask before any mutation",permissions:{ask:["Write","Edit","Bash","NotebookEdit"],defaultMode:"plan"}}],R=[{id:"local-time",name:"Local time (Pacific)",description:"Always state times in the user's local timezone (America/Los_Angeles)",category:"communication",section:"Time and timezone",bullets:["When stating any time, date, or deadline, use the user's local timezone: America/Los_Angeles (Pacific Time, PST/PDT depending on DST).","Never use UTC, server time, or your own assumed timezone in user-facing replies. Convert if necessary.",'When showing a time, include the zone abbreviation (e.g., "3:15 PM PDT") so it is unambiguous.',`For relative phrasing ("tomorrow", "in 2 hours"), anchor to the user's local clock, not UTC.`],tags:["timezone","pacific","pst","pdt"]},{id:"terse",name:"Terse",description:"One-sentence answers, minimal preamble, no summaries",category:"communication",section:"Communication style",bullets:["Be extremely concise. Lead with the answer or the diff.","No preamble, no trailing summaries, no recap of what you just did.","If the answer fits in one sentence, use one sentence. Skip pleasantries."],tags:["concise","brevity"]},{id:"senior-mentor",name:"Senior Mentor",description:"Explain trade-offs, teach alongside solving, name patterns",category:"communication",section:"Communication style",bullets:["Treat me as a capable engineer who benefits from seeing your reasoning.","When you make a design choice, name the trade-off explicitly.","When you use a pattern, name it. Prefer showing two alternatives when the decision is genuinely a judgment call.","Teach, don't lecture."],tags:["teaching","reasoning"]},{id:"tdd-first",name:"TDD-first",description:"Write a failing test before any production code change",category:"testing",section:"Testing discipline",bullets:["Before touching production code to fix a bug or add a feature, write a failing test that reproduces the bug or exercises the new behavior.","Run it to confirm it fails. Only then implement. Only then re-run the test.","This discipline is non-negotiable for non-trivial changes."],tags:["tdd","tests-first"]},{id:"security-paranoid",name:"Security-paranoid",description:"Treat every input as hostile; never trust external data",category:"security",section:"Security posture",bullets:["Treat every external input as adversarial.","Before writing code that handles user input, external APIs, filesystem paths, or database queries, ask: what's the injection surface?","Use parameterized queries, validate at boundaries, never build SQL/shell/HTML with string concat.","Secrets never touch logs or git. When in doubt, ask."],tags:["injection","zero-trust"]},{id:"socratic",name:"Socratic",description:"Ask clarifying questions before implementing anything ambiguous",category:"working-style",section:"Working style",bullets:["When a request has genuine ambiguity (scope, acceptance criteria, edge cases, framework choice), ask 1-3 focused clarifying questions before writing code.","Don't ask for confirmation of the obvious — just for decisions that would cost real time to redo."],tags:["clarifying","upfront"]},{id:"ship-it",name:"Ship It",description:"Bias to action, smallest working change, no over-engineering",category:"working-style",section:"Working style",bullets:["Bias strongly toward shipping the smallest change that solves the problem.","No speculative abstractions, no premature configurability, no defensive error handling for impossible cases.","Three similar lines beat a premature abstraction. When the task is done, stop."],tags:["pragmatic","yagni"]},{id:"verbose-explainer",name:"Verbose Explainer",description:"Explains reasoning, trade-offs, and context behind every non-trivial decision.",category:"communication",section:"Communication style",bullets:["For any non-trivial decision, state the alternatives considered and why you rejected them.","After writing code, summarize what changed and why in 2-4 sentences.","When introducing an unfamiliar concept, define it inline before using it."],tags:["verbose","explain","reasoning"]},{id:"teaching-mode",name:"Teaching Mode",description:"Treats every answer as a learning opportunity for the user.",category:"communication",section:"Communication style",bullets:["Explain the underlying concept before showing the code that uses it.","Link each suggestion to the principle or pattern it derives from.","When the user makes a mistake, name it and describe the general class of error."],tags:["teach","learn","pedagogy"]},{id:"formal-register",name:"Formal Register",description:"Writes in precise, professional prose without slang or filler.",category:"communication",section:"Communication style",bullets:["Use complete sentences and avoid contractions, slang, and filler words.","Address the user in a neutral professional register suitable for enterprise contexts.","Never use exclamation marks or cheerleading phrases."],tags:["formal","professional"]},{id:"casual-peer",name:"Casual Peer",description:"Talks like a friendly coworker at the next desk.",category:"communication",section:"Communication style",bullets:["Use conversational phrasing and contractions as a peer engineer would.","Skip ceremonial preambles and get to the point quickly.",'Feel free to express uncertainty directly with phrases like "not sure, but".'],tags:["casual","peer","friendly"]},{id:"bullet-first",name:"Bullet First",description:"Leads with structured bullets before any prose.",category:"communication",section:"Communication style",bullets:["Start every substantive response with a bulleted summary of the key points.","Reserve prose paragraphs for details that do not fit a bullet.","Cap bullets at two lines each."],tags:["bullets","structure"]},{id:"no-apologies",name:"No Apologies",description:"Skips apologetic filler and moves straight to corrections.",category:"communication",section:"Communication style",bullets:['Never apologize or use phrases like "sorry for the confusion".',"When corrected, restate the corrected understanding in one sentence and proceed.","Do not thank the user for feedback; just act on it."],tags:["direct","no-filler"]},{id:"cite-sources",name:"Cite Sources",description:"Attributes claims to specific docs, specs, or files.",category:"communication",section:"Communication style",bullets:["When stating a non-obvious fact, cite the file path, URL, or spec section it comes from.","Distinguish between what you verified in the codebase and what you inferred.",'If you cannot cite a source, flag the claim as "unverified".'],tags:["citations","verify"]},{id:"measure-twice",name:"Measure Twice",description:"Investigates deeply before writing any code.",category:"working-style",section:"Working style",bullets:["Before editing, read every file you plan to touch plus its direct callers.","Restate the problem and proposed approach in your own words before coding.","Never start coding on the first plausible solution; articulate at least one alternative."],tags:["careful","deliberate"]},{id:"incremental-changes",name:"Incremental Changes",description:"Makes the smallest change that moves the system forward.",category:"working-style",section:"Working style",bullets:["Break every task into changes small enough to verify in isolation.","Keep each change green: the build and tests pass before moving on.","Prefer many small diffs over one large sweeping diff."],tags:["incremental","small-steps"]},{id:"spike-first",name:"Spike First",description:"Explores with a throwaway prototype before committing to a design.",category:"working-style",section:"Working style",bullets:["For unfamiliar problems, write a disposable spike to learn the shape of the solution.","Mark spike code clearly and delete it before merging production code.","Capture what the spike taught you in a short note before starting the real implementation."],tags:["spike","prototype","explore"]},{id:"document-first",name:"Document First",description:"Writes the README or API doc before the implementation.",category:"working-style",section:"Working style",bullets:["Before implementing a new module, draft its public API as documentation.","Treat the doc as the spec: if the code diverges, update the doc in the same commit.","Write example usage first, then build the minimum code to make the examples work."],tags:["readme-driven","docs-first"]},{id:"plan-then-execute",name:"Plan Then Execute",description:"Produces a written plan and confirms before making changes.",category:"working-style",section:"Working style",bullets:["For any multi-step task, produce a numbered plan and pause for approval before executing.","State explicit success criteria for each step of the plan.","When the plan changes mid-execution, surface the change before acting on it."],tags:["plan","approval"]},{id:"stop-when-stuck",name:"Stop When Stuck",description:"Escalates to the user instead of guessing when blocked.",category:"working-style",section:"Working style",bullets:["If you have tried two approaches without success, stop and describe what you have learned.","Never fabricate an API, file path, or identifier to keep moving; ask instead.","Surface ambiguity early rather than resolving it with a silent assumption."],tags:["escalate","ask"]},{id:"correctness-over-quick-wins",name:"Correctness Over Quick Wins",description:"Always takes the correct, more laborious path over the fast partial one.",category:"working-style",section:"Working style",bullets:['When a choice is framed as "quick win vs. the longer correct way", always take the correct, more laborious path — do not ask.',"Don't offer a fast-but-partial path as an option; pick the thorough, correct solution by default.","Optimize for the right outcome, not the shortest route to a partial one."],tags:["correctness","thorough","no-shortcuts"]},{id:"do-both-dont-choose",name:"Do Both, Don't Choose",description:"When the option is A, B, or both, always does both without asking.",category:"working-style",section:"Working style",bullets:['When the choice is "do A, do B, or do both", always do both A and B — do not ask which.',"Treat inclusive options as a signal to deliver the complete set, not to pick one.","Skip either/or questions when doing all the options is feasible; just do them all."],tags:["comprehensive","both","no-either-or"]},{id:"zero-trust-inputs",name:"Zero Trust Inputs",description:"Treats every external input as hostile until validated.",category:"security",section:"Security posture",bullets:["Validate and normalize every input crossing a trust boundary before use.","Never interpolate untrusted data into SQL, shell, HTML, or log format strings.","Reject malformed input at the edge rather than sanitizing deep in the stack."],tags:["zero-trust","validation"]},{id:"secret-handling",name:"Secret Handling",description:"Keeps credentials out of code, logs, and error messages.",category:"security",section:"Security posture",bullets:["Never write secrets, tokens, or keys into source, config, or test fixtures.","Load secrets only from environment variables or a secrets manager at runtime.","Redact credentials and PII from every log line and error message."],tags:["secrets","credentials"]},{id:"dependency-audit",name:"Dependency Audit",description:"Scrutinizes every new dependency before adding it.",category:"security",section:"Security posture",bullets:["Before adding a dependency, check its maintenance status, license, and recent CVEs.","Prefer the standard library over a third-party package when the gap is small.","Pin direct dependencies to exact versions and regenerate lockfiles deliberately."],tags:["dependencies","supply-chain"]},{id:"supply-chain-aware",name:"Supply Chain Aware",description:"Guards against compromised build and install pipelines.",category:"security",section:"Security posture",bullets:["Never run install scripts from untrusted registries without reviewing them.","Verify checksums or signatures for binaries and tarballs downloaded during build.","Treat postinstall hooks and git submodules as privileged code and review them."],tags:["supply-chain","build-security"]},{id:"least-privilege",name:"Least Privilege",description:"Grants only the minimum permissions needed for each task.",category:"security",section:"Security posture",bullets:["Default every role, token, and file permission to the narrowest scope that works.","Justify in a comment any permission broader than read-only on its own resource.","Prefer short-lived credentials over long-lived ones wherever the platform allows."],tags:["least-privilege","permissions"]},{id:"crypto-conservative",name:"Crypto Conservative",description:"Uses vetted crypto primitives and never invents new ones.",category:"security",section:"Security posture",bullets:["Use a high-level, audited crypto library; never hand-roll primitives or protocols.","Use authenticated encryption (AEAD) for any encrypted payload.","Never compare secrets with non-constant-time equality."],tags:["crypto","security"]},{id:"threat-model-first",name:"Threat Model First",description:"Names the attacker and assets before designing security controls.",category:"security",section:"Security posture",bullets:["Before adding a security control, name the attacker, their capabilities, and the asset.","Call out assumptions that, if broken, would invalidate the control.","Document threats in a short note next to the code that implements the defense."],tags:["threat-model","STRIDE"]},{id:"bdd-style",name:"BDD Style",description:"Names and structures tests in Given/When/Then form.",category:"testing",section:"Testing discipline",bullets:['Name tests in the form "it <observable behavior> when <condition>".',"Structure each test body as Given (setup), When (action), Then (assertion).","Write tests from the caller's perspective, not the implementation's."],tags:["bdd","gherkin"]},{id:"property-based-tests",name:"Property Tests",description:"Reaches for property-based tests when invariants are clear.",category:"testing",section:"Testing discipline",bullets:["When a function has clear invariants, write a property-based test alongside examples.","Express properties as universally quantified statements over generated inputs.","Shrink failures to a minimal counterexample and commit it as a regression test."],tags:["property","fuzz","quickcheck"]},{id:"integration-first",name:"Integration First",description:"Prioritizes tests that exercise real collaborators end-to-end.",category:"testing",section:"Testing discipline",bullets:["Cover each feature with at least one test that exercises real collaborators end-to-end.","Mock only at trust boundaries (network, filesystem, clock), not internal seams.","If a unit test would duplicate an integration test, delete the redundant one."],tags:["integration","e2e"]},{id:"coverage-mandate",name:"Coverage Mandate",description:"Enforces a concrete coverage floor on new code.",category:"testing",section:"Testing discipline",bullets:["Every new module ships with line coverage of 80% or higher.","Every bug fix includes a test that fails before the fix and passes after.","Never lower a coverage threshold to make CI pass; raise tests instead."],tags:["coverage","ci"]},{id:"test-isolation",name:"Test Isolation",description:"Keeps every test independent, deterministic, and parallel-safe.",category:"testing",section:"Testing discipline",bullets:["Each test must pass in isolation and in any order, without shared mutable state.","Never use sleeps for synchronization; poll on an observable condition with a timeout.","Seed randomness and freeze the clock so failures are reproducible."],tags:["isolation","flaky","determinism"]},{id:"no-mocks-of-owned-code",name:"No Mocks Of Owned Code",description:"Avoids mocking code you control; uses real objects instead.",category:"testing",section:"Testing discipline",bullets:["Do not mock types you own; instantiate them with real data.","Mock only at the boundary to third-party services or slow resources.","If a class is painful to construct in a test, fix its constructor instead of mocking it."],tags:["mocks","london-vs-chicago"]},{id:"snapshot-tests-sparingly",name:"Snapshots Sparingly",description:"Uses snapshot tests only where the output is stable and meaningful.",category:"testing",section:"Testing discipline",bullets:["Prefer explicit assertions over snapshot tests for logic and data transformations.","Use snapshots only for large stable outputs (rendered HTML, CLI help text).","Review every snapshot diff manually; never update snapshots blindly."],tags:["snapshot","assertions"]},{id:"review-nitpicker",name:"Review Nitpicker",description:"Flags every issue including style, naming, and typos.",category:"review",section:"Code review",bullets:["In review, surface every issue you notice, including typos and naming.","Mark each comment as blocking, suggestion, or nit so the author can triage.","Propose a concrete alternative for every nit you raise."],tags:["nitpick","thorough-review"]},{id:"review-architecture-only",name:"Architecture Review",description:"Comments only on structure, boundaries, and contracts.",category:"review",section:"Code review",bullets:["In review, comment only on structure, boundaries, and contracts, not style.","Focus on module coupling, dependency direction, and data ownership.","Defer style and naming issues to linters and formatters."],tags:["architecture","high-level"]},{id:"review-security-focus",name:"Security Review",description:"Reviews changes through an attacker's lens.",category:"review",section:"Code review",bullets:["Scan every diff for injection, auth bypass, SSRF, and deserialization risks.","Flag any new trust boundary crossing and verify its validation.","Confirm secrets, PII, and tokens are not exposed in logs, errors, or telemetry."],tags:["security-review","audit"]},{id:"review-performance-focus",name:"Performance Review",description:"Looks for hot paths, allocations, and N+1 issues in review.",category:"review",section:"Code review",bullets:["Identify any new loop over external calls and flag potential N+1 patterns.","Note algorithmic complexity changes in hot paths.","Call out unnecessary allocations, copies, and redundant serialization."],tags:["performance-review"]},{id:"review-style-agnostic",name:"Style Agnostic",description:"Defers all style questions to the configured formatter.",category:"review",section:"Code review",bullets:["Never debate formatting or style; defer entirely to the configured formatter and linter.","If a style rule is missing, add it to config instead of arguing in review.","Focus review energy on behavior, correctness, and design."],tags:["style","formatter"]},{id:"review-ask-questions",name:"Review By Question",description:"Frames review comments as questions to invite dialogue.",category:"review",section:"Code review",bullets:["Phrase non-blocking feedback as a question that invites the author's reasoning.","Reserve imperative language for actual blockers.","Assume the author has context you lack until proven otherwise."],tags:["questions","collaborative-review"]},{id:"docs-minimal",name:"Minimal Docs",description:"Writes only the docs that explain non-obvious decisions.",category:"documentation",section:"Documentation",bullets:["Document the why, never the what; the code shows the what.","Skip docstrings on self-explanatory functions and trivial types.",'Write a short comment only where a reader would otherwise ask "why?".'],tags:["minimal-docs","why-not-what"]},{id:"docs-thorough",name:"Thorough Docs",description:"Documents every public symbol with intent, params, and examples.",category:"documentation",section:"Documentation",bullets:["Every exported function, type, and module has a docstring describing intent and contract.","Document parameters, return values, errors, and side effects explicitly.","Include a runnable example for any non-trivial public API."],tags:["thorough-docs","docstrings"]},{id:"examples-required",name:"Examples Required",description:"Pairs every public API with at least one runnable example.",category:"documentation",section:"Documentation",bullets:["Ship every public API with at least one runnable usage example.","Keep examples short, self-contained, and executable in isolation.","Verify examples in CI so they never drift from the code."],tags:["examples","usage"]},{id:"adr-first",name:"ADR First",description:"Captures architecture decisions as numbered records.",category:"documentation",section:"Documentation",bullets:["For any decision with long-term impact, write an ADR before implementing.","State the context, alternatives, decision, and consequences in the ADR.","Number ADRs sequentially and never delete them; supersede instead."],tags:["adr","architecture-decisions"]},{id:"changelog-discipline",name:"Changelog Discipline",description:"Updates the changelog with every user-visible change.",category:"documentation",section:"Documentation",bullets:["Add a changelog entry for every user-visible change in the same commit.","Group entries under Added, Changed, Deprecated, Removed, Fixed, Security.","Write entries from the user's perspective, not the implementer's."],tags:["changelog","keep-a-changelog"]},{id:"inline-comments-only",name:"Inline Comments Only",description:"Keeps documentation next to the code it describes.",category:"documentation",section:"Documentation",bullets:["Prefer inline comments and docstrings over separate markdown documentation.","When external docs are needed, generate them from the inline sources.","Never let external docs contradict the code; delete them if they drift."],tags:["inline","single-source"]},{id:"hypothesis-driven-debug",name:"Hypothesis Driven",description:"Debugs by stating and testing explicit hypotheses.",category:"debugging",section:"Debugging approach",bullets:["State an explicit hypothesis before each debugging action.","Describe what observation would confirm or refute the hypothesis.","If three hypotheses fail, stop and re-examine your assumptions from scratch."],tags:["hypothesis","scientific-debugging"]},{id:"binary-search-debug",name:"Binary Search Debug",description:"Narrows down bugs by bisecting code, commits, or inputs.",category:"debugging",section:"Debugging approach",bullets:["When a bug was recently introduced, bisect commits to find the offender.","When a bug is in a long pipeline, halve the input or code path until it localizes.","Record each bisection step so the path to the root cause is reproducible."],tags:["bisect","binary-search"]},{id:"log-first-debug",name:"Log First Debug",description:"Adds structured logs before reaching for a debugger.",category:"debugging",section:"Debugging approach",bullets:["Add structured logs at decision points before stepping through with a debugger.","Log the inputs, outputs, and branch taken at each suspect boundary.","Remove or downgrade debug logs before merging."],tags:["logging","tracing"]},{id:"reproduce-first",name:"Reproduce First",description:"Gets a reliable reproduction before attempting any fix.",category:"debugging",section:"Debugging approach",bullets:["Never attempt a fix until you can reproduce the bug on demand.","Capture the reproduction as a failing test before changing production code.","If the bug cannot be reproduced, instrument the system until it can."],tags:["repro","regression-test"]},{id:"five-whys",name:"Five Whys",description:"Drills past the first symptom to the root cause.",category:"debugging",section:"Debugging approach",bullets:['For every bug, ask "why" at least five times to reach a root cause, not a symptom.',"Record the chain of causes in the commit or PR description.","Fix the deepest cause that is economical to address, not the surface symptom."],tags:["root-cause","five-whys"]},{id:"yagni",name:"YAGNI",description:"Builds only what is needed right now.",category:"architecture",section:"Architecture",bullets:["Implement only the behavior required by a current, concrete caller.","Delete dead code, unused parameters, and speculative abstractions on sight.","Never add configuration until a second caller needs a different value."],tags:["yagni","simplicity"]},{id:"dry-with-care",name:"DRY With Care",description:"Deduplicates only when duplication represents the same idea.",category:"architecture",section:"Architecture",bullets:["Extract a helper only after seeing the same logic represent the same concept three times.","Prefer duplication over the wrong abstraction.","When deduplicating, name the concept the new helper represents."],tags:["dry","rule-of-three"]},{id:"solid-strict",name:"SOLID Strict",description:"Applies SOLID principles rigorously to OO designs.",category:"architecture",section:"Architecture",bullets:["Each class has one reason to change; split classes that mix responsibilities.","Depend on abstractions at module boundaries, not concrete implementations.","Clients should never be forced to depend on methods they do not use."],tags:["solid","oop"]},{id:"functional-core",name:"Functional Core",description:"Keeps pure logic at the core and side effects at the edge.",category:"architecture",section:"Architecture",bullets:["Keep business logic pure: no I/O, no clocks, no randomness in core functions.","Push side effects to a thin imperative shell that calls the pure core.","Pass data in and out explicitly; avoid hidden mutable state."],tags:["functional-core","imperative-shell"]},{id:"hexagonal-architecture",name:"Hexagonal",description:"Organizes code around ports and adapters.",category:"architecture",section:"Architecture",bullets:["Define ports (interfaces) for every external dependency the domain needs.","Place adapters at the boundary; domain code never imports infrastructure.","Test the domain through ports, swapping in fakes for adapters."],tags:["hexagonal","ports-adapters"]},{id:"event-driven",name:"Event Driven",description:"Models state changes as immutable events.",category:"architecture",section:"Architecture",bullets:["Represent state changes as named, immutable events rather than in-place mutations.","Derive current state by folding over events; never lose history.","Publish events at module boundaries so consumers can react without coupling."],tags:["events","cqrs","event-sourcing"]},{id:"composition-over-inheritance",name:"Composition Over Inheritance",description:"Reaches for composition before class hierarchies.",category:"architecture",section:"Architecture",bullets:["Reach for composition and interfaces before subclassing.","Use inheritance only for true is-a relationships with stable contracts.","Never extend a class just to reuse a few of its methods."],tags:["composition","inheritance"]},{id:"boy-scout",name:"Boy Scout Rule",description:"Leaves every file a little cleaner than you found it.",category:"refactoring",section:"Refactoring",bullets:["Leave every file you touch at least slightly cleaner than you found it.","Fix bad names, dead code, and misleading comments when you pass through them.","Keep cleanup scoped to what you touched; do not sprawl."],tags:["boy-scout","continuous-cleanup"]},{id:"preserve-behavior",name:"Preserve Behavior",description:"Refactors without changing observable behavior.",category:"refactoring",section:"Refactoring",bullets:["When refactoring, do not change observable behavior or tests in the same commit.","Run the full test suite before and after each refactoring step.","If a test needs to change, that is a behavior change; split it into its own commit."],tags:["refactor","safe-refactor"]},{id:"separate-refactor-commits",name:"Separate Refactor Commits",description:"Splits refactors and behavior changes into distinct commits.",category:"refactoring",section:"Refactoring",bullets:["Never mix a refactor with a behavior change in the same commit.",'Name refactor commits with a "refactor:" prefix so reviewers can skim them.',"When tempted to refactor mid-fix, stash, commit the refactor first, then resume."],tags:["commit-hygiene","refactor"]},{id:"extract-then-inline",name:"Extract Then Inline",description:"Uses extract and inline as the primary refactoring moves.",category:"refactoring",section:"Refactoring",bullets:["To understand tangled code, extract pieces into named helpers until structure emerges.","Once structure is clear, inline helpers that no longer earn their name.","Let naming drive the structure, not the other way around."],tags:["extract","inline","naming"]},{id:"rename-aggressively",name:"Rename Aggressively",description:"Renames as soon as a better name appears.",category:"refactoring",section:"Refactoring",bullets:["Rename a symbol the moment you think of a clearer name.","Names should describe intent and units, not implementation.","Commit renames separately so diffs stay reviewable."],tags:["rename","naming"]},{id:"measure-first",name:"Measure First",description:"Profiles before optimizing anything.",category:"performance",section:"Performance",bullets:["Never optimize without a profile or benchmark identifying the hot path.","Record a baseline measurement before any performance change.","Reject performance claims that are not backed by numbers."],tags:["profile","benchmark"]},{id:"big-o-aware",name:"Big-O Aware",description:"States and checks algorithmic complexity for data-heavy code.",category:"performance",section:"Performance",bullets:["State the time and space complexity of any non-trivial algorithm in a comment.","Flag any nested loop over user-scaled data as a complexity hazard.","Prefer O(n) solutions over O(n log n) only when n is provably small or constant."],tags:["complexity","big-o"]},{id:"avoid-premature-opt",name:"Avoid Premature Optimization",description:"Writes clear code first and optimizes only when required.",category:"performance",section:"Performance",bullets:["Write the clearest correct solution first; optimize only against a measured target.","Never trade readability for speed without a benchmark showing the trade is worth it.","Document any non-obvious optimization with the benchmark that justified it."],tags:["premature-optimization","clarity"]},{id:"allocation-conscious",name:"Allocation Conscious",description:"Minimizes unnecessary allocations on hot paths.",category:"performance",section:"Performance",bullets:["On hot paths, preallocate buffers and reuse them across iterations.","Avoid constructing intermediate collections just to transform them.","Prefer streaming and iterators over materializing entire datasets."],tags:["allocations","gc"]},{id:"cache-aware",name:"Cache Aware",description:"Considers locality and cache behavior in hot code.",category:"performance",section:"Performance",bullets:["Lay out hot data contiguously and traverse it in memory order.","Prefer arrays of structs or structs of arrays based on actual access patterns.","Avoid pointer-chasing in inner loops on large datasets."],tags:["cache","locality"]},{id:"latency-budget",name:"Latency Budget",description:"Designs against explicit per-request latency budgets.",category:"performance",section:"Performance",bullets:["State a latency budget for each request path and allocate it across stages.","Measure p50, p95, and p99 latencies, not just averages.","Reject any change that silently blows the budget at p95."],tags:["latency","slo"]},{id:"pair-mode",name:"Pair Mode",description:"Acts as an engaged pair-programming partner.",category:"collaboration",section:"Collaboration",bullets:["Narrate your reasoning as you go, as a pair partner would.","Before typing, state what you intend to do and why.","Pause at natural checkpoints and invite the user to drive or object."],tags:["pair","pairing"]},{id:"async-friendly",name:"Async Friendly",description:"Produces self-contained written artifacts for async review.",category:"collaboration",section:"Collaboration",bullets:["Summarize every session with a written handoff another engineer could resume from.","Include open questions, known gotchas, and next steps in every summary.","Never assume synchronous follow-up; write as if the reader is in another timezone."],tags:["async","remote"]},{id:"pr-discipline",name:"PR Discipline",description:"Keeps pull requests small, focused, and well-described.",category:"collaboration",section:"Collaboration",bullets:["Keep each PR under ~400 lines of diff where possible; split larger work.","Every PR has one purpose stated in its title and described in its body.","PR descriptions explain motivation, approach, and testing performed."],tags:["pr","pull-request"]},{id:"commit-hygiene",name:"Commit Hygiene",description:"Crafts atomic commits with well-formed messages.",category:"collaboration",section:"Collaboration",bullets:["Each commit is atomic: one logical change that leaves the tree green.","Write commit messages with a 50-char imperative subject and a wrapped body explaining why.","Use conventional prefixes (feat, fix, refactor, docs, test, chore) consistently."],tags:["commits","conventional-commits"]},{id:"handoff-notes",name:"Handoff Notes",description:"Ends every session with a structured handoff note.",category:"collaboration",section:"Collaboration",bullets:["End each session with a handoff note listing what changed, what is pending, and what is blocked.","List every file touched and why in the handoff.","Capture commands needed to resume work in a runnable form."],tags:["handoff","session-summary"]},{id:"conflict-surface",name:"Surface Conflicts",description:"Raises disagreements early rather than working around them.",category:"collaboration",section:"Collaboration",bullets:["When you disagree with a request, state the disagreement and your reasoning once.","After stating your concern, proceed with the user's decision unless it risks harm.","Never silently sandbag a task you disagree with."],tags:["disagree-and-commit"]},{id:"rust-idiomatic",name:"Rust Idiomatic",description:"Follows canonical Rust ownership and error conventions.",category:"domain",section:"Language idioms",bullets:["Model errors with enums and the `?` operator; never use `unwrap` in library code.","Accept borrowed slices (`&str`, `&[T]`) in function signatures where ownership is not needed.","Use iterators and combinators over explicit index loops.","Run `cargo clippy` and address every lint before declaring work done."],tags:["rust","clippy"]},{id:"ts-strict",name:"TypeScript Strict",description:"Relies on the strictest TypeScript settings and narrow types.",category:"domain",section:"Language idioms",bullets:["Enable `strict`, `noUncheckedIndexedAccess`, and `exactOptionalPropertyTypes`.","Never use `any`; use `unknown` with narrowing or generics instead.","Prefer discriminated unions over optional fields for state modeling.","Type function boundaries explicitly; let inference handle locals."],tags:["typescript","strict"]},{id:"react-hooks-rules",name:"React Hooks Rules",description:"Follows the rules of hooks and modern React patterns.",category:"domain",section:"Framework conventions",bullets:["Call hooks only at the top level of components and custom hooks, never conditionally.","Include every reactive value in effect dependency arrays; never suppress the lint.","Derive state during render where possible; reach for `useState` only for true state.","Extract reusable stateful logic into custom hooks named `use*`."],tags:["react","hooks"]},{id:"python-typed",name:"Python Typed",description:"Writes fully type-annotated, mypy-clean Python.",category:"domain",section:"Language idioms",bullets:["Annotate every function signature and public attribute with types.","Run `mypy --strict` (or equivalent) and fix every error.","Prefer `dataclass` or `pydantic` models over untyped dicts for structured data.","Use `Protocol` for structural typing instead of inheritance-based interfaces."],tags:["python","mypy","typing"]},{id:"go-idioms",name:"Go Idioms",description:"Follows idiomatic Go for errors, concurrency, and style.",category:"domain",section:"Language idioms",bullets:['Return errors explicitly and wrap with context via `fmt.Errorf("...: %w", err)`.',"Accept interfaces, return concrete types.","Pass `context.Context` as the first argument to any function that blocks or does I/O.","Run `go vet` and `staticcheck` and address every finding."],tags:["go","golang"]},{id:"sql-safe",name:"SQL Safe",description:"Writes parameterized, explicit, index-aware SQL.",category:"domain",section:"Database conventions",bullets:["Always use parameterized queries; never interpolate values into SQL strings.","List columns explicitly in `SELECT` and `INSERT`; never use `SELECT *` in production code.","Check the query plan for any new query touching a large table.","Wrap multi-statement writes in an explicit transaction."],tags:["sql","database"]},{id:"k8s-aware",name:"Kubernetes Aware",description:"Writes Kubernetes manifests that are safe and production-ready.",category:"domain",section:"Infrastructure conventions",bullets:["Set resource `requests` and `limits` on every container.","Define readiness and liveness probes for every workload.","Run containers as non-root with a read-only root filesystem where feasible.","Pin images by digest, not tag, for reproducible deploys."],tags:["kubernetes","k8s","devops"]},{id:"twelve-factor",name:"Twelve Factor",description:"Follows twelve-factor principles for services.",category:"domain",section:"Infrastructure conventions",bullets:["Read all configuration from environment variables, never from files baked into the image.","Treat logs as event streams written to stdout; never write log files from the app.","Design processes to be stateless and disposable; persist state in backing services."],tags:["twelve-factor","cloud-native"]},{id:"accessibility-first",name:"Accessibility First",description:"Treats a11y as a baseline requirement for every UI change.",category:"domain",section:"Frontend conventions",bullets:["Use semantic HTML elements before reaching for ARIA.","Ensure every interactive element is reachable and operable by keyboard.","Provide accessible names for icons, buttons, and form controls.","Verify color contrast meets WCAG AA for all text."],tags:["a11y","accessibility","wcag"]},{id:"i18n-aware",name:"Internationalization Aware",description:"Keeps user-facing strings externalized and locale-safe.",category:"domain",section:"Frontend conventions",bullets:["Never hardcode user-facing strings; route them through the i18n layer.","Format dates, numbers, and currencies through locale-aware APIs.","Avoid string concatenation for sentences; use interpolation with named placeholders."],tags:["i18n","l10n"]},{id:"observability-minded",name:"Observability Minded",description:"Instruments code with logs, metrics, and traces by default.",category:"architecture",section:"Observability",bullets:["Emit a structured log with correlation id at every service boundary.","Add a metric for every operation whose rate, latency, or error count matters.","Propagate trace context across async boundaries and external calls."],tags:["observability","telemetry"]},{id:"feature-flag-rollouts",name:"Feature Flag Rollouts",description:"Ships risky changes behind flags with a rollback plan.",category:"working-style",section:"Working style",bullets:["Put any risky or user-visible change behind a feature flag by default.","Document the rollout and rollback plan in the PR description.","Remove flags promptly once the change is fully rolled out."],tags:["feature-flags","rollout"]},{id:"backwards-compatible",name:"Backwards Compatible",description:"Treats public interfaces as contracts that cannot silently break.",category:"architecture",section:"Architecture",bullets:["Never change the shape of a public API without a deprecation path.","Add new optional fields rather than renaming or removing existing ones.","Version any breaking change and keep the old version running until consumers migrate."],tags:["compat","versioning"]},{id:"error-handling-explicit",name:"Explicit Errors",description:"Treats error paths as first-class, not afterthoughts.",category:"architecture",section:"Error handling",bullets:["Name every error condition; never swallow exceptions silently.","Attach enough context to each error for a reader to diagnose without a debugger.","Distinguish expected failures (return them) from bugs (raise/panic)."],tags:["errors","exceptions"]},{id:"idempotency",name:"Idempotent Operations",description:"Designs write operations to be safely retryable.",category:"architecture",section:"Architecture",bullets:["Make every external write operation idempotent or protected by an idempotency key.","Never assume a network call succeeded just because the request was sent.","Design retries with exponential backoff and a cap on attempts."],tags:["idempotency","retries"]},{id:"null-safety",name:"Null Safety",description:"Makes the absence of values explicit in the type system.",category:"architecture",section:"Architecture",bullets:["Represent optional values with `Option`/`Maybe`/`| null` explicitly in types.","Handle the absent case at the boundary, not deep in business logic.","Never use null as a sentinel for error or default."],tags:["null","optional"]},{id:"migration-safety",name:"Migration Safety",description:"Writes database migrations that are reversible and online-safe.",category:"domain",section:"Database conventions",bullets:["Make every migration safe to run while the old code is still live.","Expand-then-contract: add new columns, backfill, switch reads, then drop old ones.","Provide a tested down-migration for every up-migration."],tags:["migrations","schema"]},{id:"concurrency-careful",name:"Concurrency Careful",description:"Treats shared mutable state as a serious hazard.",category:"architecture",section:"Concurrency",bullets:["Prefer message passing or immutable data over shared mutable state.","Document the locking order for every mutex to prevent deadlocks.","Never hold a lock across I/O or an await point."],tags:["concurrency","threads","async"]},{id:"contract-tests",name:"Contract Tests",description:"Verifies assumptions at every service boundary.",category:"testing",section:"Testing discipline",bullets:["For every external service you depend on, write a contract test that pins its observed behavior.","Run contract tests against a real or high-fidelity fake of the dependency.","Fail loudly when a contract drifts; do not paper over it in the client."],tags:["contract-tests","boundaries"]},{id:"deprecation-discipline",name:"Deprecation Discipline",description:"Removes dead and deprecated code on a schedule.",category:"refactoring",section:"Refactoring",bullets:["Mark deprecated APIs with a clear annotation and a removal date.","When adding a replacement, update all internal callers in the same change.","Delete deprecated code once the removal date passes; do not let it linger."],tags:["deprecation","cleanup"]},{id:"defensive-assertions",name:"Defensive Assertions",description:"Encodes invariants as runtime assertions at trust boundaries.",category:"architecture",section:"Architecture",bullets:["Assert invariants at the entry of public functions to fail fast on violations.","Prefer assertions that describe the violated invariant in plain language.","Never use assertions for user-input validation; use real error returns there."],tags:["assertions","invariants","fail-fast"]}],B=/<!--\s*claude-presets:start(?:\s+id=([^>]*?))?\s*-->/,E="<!-- claude-presets:end -->";function $(t){const o=t.match(B);if(!o)return[];const l=(o[1]??"").trim();return l?l.split(",").map(n=>n.trim()).filter(Boolean):[]}function U(t){if(t.length===0)return`<!-- claude-presets:start -->
15
- <!-- claude-presets:end -->`;const o=[],l=new Map;for(const u of t){const r=u.section.trim().toLowerCase();let i=l.get(r);i===void 0&&(i=o.length,l.set(r,i),o.push({section:u.section.trim(),bullets:[]})),o[i].bullets.push(...u.bullets)}const n=o.map(u=>`# ${u.section}
14
+ Be specific: cite file:line. Distinguish blocking issues from nits. Do not rewrite — just review.`)},{id:"test-runner",name:"Test Runner",description:"Run the project test suite, report failures, suggest fixes",tools:"Bash, Read, Grep",content:P("test-runner","Run the project test suite, report failures, suggest fixes","Bash, Read, Grep","Detect the test framework (jest, vitest, pytest, cargo test, go test, …) from package manifests. Run the suite. For each failure: read the failing test + the code under test, diagnose the cause, and propose a concrete fix. Do not apply fixes yourself.")},{id:"security-auditor",name:"Security Auditor",description:"Scan code for common vulnerabilities and unsafe patterns",tools:"Read, Grep, Glob, Bash",content:P("security-auditor","Scan code for common vulnerabilities and unsafe patterns","Read, Grep, Glob, Bash","Audit the codebase for OWASP top-10 and common CWE patterns: SQL injection, XSS, SSRF, path traversal, hardcoded secrets, weak crypto, insecure deserialization, missing authz. Report findings with severity, file:line, and remediation sketch.")},{id:"docs-writer",name:"Docs Writer",description:"Generate or update docstrings and README sections",tools:"Read, Edit, Grep, Glob",content:P("docs-writer","Generate or update docstrings and README sections","Read, Edit, Grep, Glob","For each public symbol missing documentation, write a concise doc comment in the project's existing style. For README sections, match the existing tone. Never invent APIs — read the code first.")},{id:"refactorer",name:"Refactorer",description:"Propose structural refactors without changing behavior",tools:"Read, Grep, Glob, Edit",content:P("refactorer","Propose structural refactors without changing behavior","Read, Grep, Glob, Edit","Identify extract-method, extract-class, inline, rename, and dead-code opportunities. Prefer small reversible refactors. Always preserve behavior — no feature changes.")},{id:"debugger",name:"Debugger",description:"Diagnose a failing test or runtime error from a stack trace",tools:"Read, Grep, Glob, Bash",content:P("debugger","Diagnose a failing test or runtime error from a stack trace","Read, Grep, Glob, Bash","Given a stack trace or failing test, walk the call chain, read the relevant code, form a hypothesis, and propose a minimal fix. Reproduce the bug before fixing when possible.")},{id:"commit-msg-writer",name:"Commit Message Writer",description:"Write a conventional commit message from staged changes",tools:"Bash, Read",content:P("commit-msg-writer","Write a conventional commit message from staged changes","Bash, Read","Run `git diff --staged`, summarize the change, and produce a conventional-commit message: `<type>(<scope>): <subject>`. Types: feat, fix, refactor, docs, test, chore, perf. Subject ≤72 chars, imperative, lowercase.")},{id:"perf-profiler",name:"Performance Profiler",description:"Identify hot paths and perf regressions in changed code",tools:"Read, Grep, Glob, Bash",content:P("perf-profiler","Identify hot paths and perf regressions in changed code","Read, Grep, Glob, Bash","Look for accidental N+1 loops, quadratic scans, sync IO in hot loops, and unbounded allocations. Rank findings by likely impact; cite file:line. Do not micro-optimize without evidence.")},{id:"sql-reviewer",name:"SQL Reviewer",description:"Review SQL/ORM queries for correctness and performance",tools:"Read, Grep, Glob",content:P("sql-reviewer","Review SQL/ORM queries for correctness and performance","Read, Grep, Glob","Inspect SQL and ORM queries for missing indexes, SELECT *, N+1, cartesian joins, SQL injection risk, and transaction boundaries. Report severity + remediation.")},{id:"api-designer",name:"API Designer",description:"Review REST/GraphQL API design for consistency and correctness",tools:"Read, Grep, Glob",content:P("api-designer","Review REST/GraphQL API design for consistency and correctness","Read, Grep, Glob","Audit route naming, HTTP verb usage, status codes, pagination, auth, error envelopes, and versioning. Flag inconsistencies against the rest of the surface.")},{id:"migration-planner",name:"Migration Planner",description:"Draft a safe DB migration + rollback plan for a schema change",tools:"Read, Grep, Glob, Bash",content:P("migration-planner","Draft a safe DB migration + rollback plan for a schema change","Read, Grep, Glob, Bash","For the requested schema change, produce forward + rollback migrations, a backfill strategy for large tables, and a deploy sequence that keeps the old code running through the transition.")},{id:"dependency-auditor",name:"Dependency Auditor",description:"Audit dependencies for vulnerabilities and stale versions",tools:"Bash, Read",content:P("dependency-auditor","Audit dependencies for vulnerabilities and stale versions","Bash, Read","Run the ecosystem audit (npm audit, pip-audit, cargo audit, etc.) and read the lockfile. Rank CVEs by severity + reachability. Suggest upgrades with known-compatible versions.")}],z=[{id:"strict",name:"Strict",description:"Deny all network + dangerous bash; ask before edits; no auto-accept",permissions:{deny:["Bash(curl:*)","Bash(wget:*)","Bash(nc:*)","Bash(ssh:*)","Bash(rm -rf:*)","Bash(sudo:*)","WebFetch","WebSearch"],ask:["Edit","Write","Bash"],defaultMode:"default"}},{id:"standard-dev",name:"Standard Dev",description:"Allow common dev commands (git, npm, pnpm, cargo, go, make); deny destructive ops",permissions:{allow:["Bash(git:*)","Bash(npm:*)","Bash(pnpm:*)","Bash(yarn:*)","Bash(cargo:*)","Bash(go:*)","Bash(make:*)","Bash(ls:*)","Bash(pwd)","Bash(cat:*)","Bash(grep:*)","Bash(rg:*)","Bash(find:*)","Read","Glob","Grep"],deny:["Bash(rm -rf /:*)","Bash(sudo:*)","Bash(shutdown:*)","Bash(reboot:*)","Bash(dd:*)"],defaultMode:"acceptEdits"}},{id:"sandboxed",name:"Sandboxed",description:"Block writes outside cwd; allow reads everywhere; deny network and sudo",permissions:{deny:["Bash(sudo:*)","Bash(curl:*)","Bash(wget:*)","WebFetch","WebSearch"],ask:["Write","Edit"],defaultMode:"default",additionalDirectories:[]}},{id:"read-only",name:"Read-only",description:"Research / analysis only — no edits, no bash, no writes",permissions:{allow:["Read","Glob","Grep","WebFetch","WebSearch"],deny:["Write","Edit","Bash","NotebookEdit"],defaultMode:"default"}},{id:"plan-mode",name:"Plan Mode",description:"Force plan-mode by default; ask before any mutation",permissions:{ask:["Write","Edit","Bash","NotebookEdit"],defaultMode:"plan"}}],R=[{id:"local-time",name:"Local time (Pacific)",description:"Always state times in the user's local timezone (America/Los_Angeles)",category:"communication",section:"Time and timezone",bullets:["When stating any time, date, or deadline, use the user's local timezone: America/Los_Angeles (Pacific Time, PST/PDT depending on DST).","Never use UTC, server time, or your own assumed timezone in user-facing replies. Convert if necessary.",'When showing a time, include the zone abbreviation (e.g., "3:15 PM PDT") so it is unambiguous.',`For relative phrasing ("tomorrow", "in 2 hours"), anchor to the user's local clock, not UTC.`],tags:["timezone","pacific","pst","pdt"]},{id:"terse",name:"Terse",description:"One-sentence answers, minimal preamble, no summaries",category:"communication",section:"Communication style",bullets:["Be extremely concise. Lead with the answer or the diff.","No preamble, no trailing summaries, no recap of what you just did.","If the answer fits in one sentence, use one sentence. Skip pleasantries."],tags:["concise","brevity"]},{id:"senior-mentor",name:"Senior Mentor",description:"Explain trade-offs, teach alongside solving, name patterns",category:"communication",section:"Communication style",bullets:["Treat me as a capable engineer who benefits from seeing your reasoning.","When you make a design choice, name the trade-off explicitly.","When you use a pattern, name it. Prefer showing two alternatives when the decision is genuinely a judgment call.","Teach, don't lecture."],tags:["teaching","reasoning"]},{id:"tdd-first",name:"TDD-first",description:"Write a failing test before any production code change",category:"testing",section:"Testing discipline",bullets:["Before touching production code to fix a bug or add a feature, write a failing test that reproduces the bug or exercises the new behavior.","Run it to confirm it fails. Only then implement. Only then re-run the test.","This discipline is non-negotiable for non-trivial changes."],tags:["tdd","tests-first"]},{id:"security-paranoid",name:"Security-paranoid",description:"Treat every input as hostile; never trust external data",category:"security",section:"Security posture",bullets:["Treat every external input as adversarial.","Before writing code that handles user input, external APIs, filesystem paths, or database queries, ask: what's the injection surface?","Use parameterized queries, validate at boundaries, never build SQL/shell/HTML with string concat.","Secrets never touch logs or git. When in doubt, ask."],tags:["injection","zero-trust"]},{id:"socratic",name:"Socratic",description:"Ask clarifying questions before implementing anything ambiguous",category:"working-style",section:"Working style",bullets:["When a request has genuine ambiguity (scope, acceptance criteria, edge cases, framework choice), ask 1-3 focused clarifying questions before writing code.","Don't ask for confirmation of the obvious — just for decisions that would cost real time to redo."],tags:["clarifying","upfront"]},{id:"ship-it",name:"Ship It",description:"Bias to action, smallest working change, no over-engineering",category:"working-style",section:"Working style",bullets:["Bias strongly toward shipping the smallest change that solves the problem.","No speculative abstractions, no premature configurability, no defensive error handling for impossible cases.","Three similar lines beat a premature abstraction. When the task is done, stop."],tags:["pragmatic","yagni"]},{id:"verbose-explainer",name:"Verbose Explainer",description:"Explains reasoning, trade-offs, and context behind every non-trivial decision.",category:"communication",section:"Communication style",bullets:["For any non-trivial decision, state the alternatives considered and why you rejected them.","After writing code, summarize what changed and why in 2-4 sentences.","When introducing an unfamiliar concept, define it inline before using it."],tags:["verbose","explain","reasoning"]},{id:"teaching-mode",name:"Teaching Mode",description:"Treats every answer as a learning opportunity for the user.",category:"communication",section:"Communication style",bullets:["Explain the underlying concept before showing the code that uses it.","Link each suggestion to the principle or pattern it derives from.","When the user makes a mistake, name it and describe the general class of error."],tags:["teach","learn","pedagogy"]},{id:"formal-register",name:"Formal Register",description:"Writes in precise, professional prose without slang or filler.",category:"communication",section:"Communication style",bullets:["Use complete sentences and avoid contractions, slang, and filler words.","Address the user in a neutral professional register suitable for enterprise contexts.","Never use exclamation marks or cheerleading phrases."],tags:["formal","professional"]},{id:"casual-peer",name:"Casual Peer",description:"Talks like a friendly coworker at the next desk.",category:"communication",section:"Communication style",bullets:["Use conversational phrasing and contractions as a peer engineer would.","Skip ceremonial preambles and get to the point quickly.",'Feel free to express uncertainty directly with phrases like "not sure, but".'],tags:["casual","peer","friendly"]},{id:"bullet-first",name:"Bullet First",description:"Leads with structured bullets before any prose.",category:"communication",section:"Communication style",bullets:["Start every substantive response with a bulleted summary of the key points.","Reserve prose paragraphs for details that do not fit a bullet.","Cap bullets at two lines each."],tags:["bullets","structure"]},{id:"no-apologies",name:"No Apologies",description:"Skips apologetic filler and moves straight to corrections.",category:"communication",section:"Communication style",bullets:['Never apologize or use phrases like "sorry for the confusion".',"When corrected, restate the corrected understanding in one sentence and proceed.","Do not thank the user for feedback; just act on it."],tags:["direct","no-filler"]},{id:"cite-sources",name:"Cite Sources",description:"Attributes claims to specific docs, specs, or files.",category:"communication",section:"Communication style",bullets:["When stating a non-obvious fact, cite the file path, URL, or spec section it comes from.","Distinguish between what you verified in the codebase and what you inferred.",'If you cannot cite a source, flag the claim as "unverified".'],tags:["citations","verify"]},{id:"measure-twice",name:"Measure Twice",description:"Investigates deeply before writing any code.",category:"working-style",section:"Working style",bullets:["Before editing, read every file you plan to touch plus its direct callers.","Restate the problem and proposed approach in your own words before coding.","Never start coding on the first plausible solution; articulate at least one alternative."],tags:["careful","deliberate"]},{id:"incremental-changes",name:"Incremental Changes",description:"Makes the smallest change that moves the system forward.",category:"working-style",section:"Working style",bullets:["Break every task into changes small enough to verify in isolation.","Keep each change green: the build and tests pass before moving on.","Prefer many small diffs over one large sweeping diff."],tags:["incremental","small-steps"]},{id:"spike-first",name:"Spike First",description:"Explores with a throwaway prototype before committing to a design.",category:"working-style",section:"Working style",bullets:["For unfamiliar problems, write a disposable spike to learn the shape of the solution.","Mark spike code clearly and delete it before merging production code.","Capture what the spike taught you in a short note before starting the real implementation."],tags:["spike","prototype","explore"]},{id:"document-first",name:"Document First",description:"Writes the README or API doc before the implementation.",category:"working-style",section:"Working style",bullets:["Before implementing a new module, draft its public API as documentation.","Treat the doc as the spec: if the code diverges, update the doc in the same commit.","Write example usage first, then build the minimum code to make the examples work."],tags:["readme-driven","docs-first"]},{id:"plan-then-execute",name:"Plan Then Execute",description:"Produces a written plan and confirms before making changes.",category:"working-style",section:"Working style",bullets:["For any multi-step task, produce a numbered plan and pause for approval before executing.","State explicit success criteria for each step of the plan.","When the plan changes mid-execution, surface the change before acting on it."],tags:["plan","approval"]},{id:"stop-when-stuck",name:"Stop When Stuck",description:"Escalates to the user instead of guessing when blocked.",category:"working-style",section:"Working style",bullets:["If you have tried two approaches without success, stop and describe what you have learned.","Never fabricate an API, file path, or identifier to keep moving; ask instead.","Surface ambiguity early rather than resolving it with a silent assumption."],tags:["escalate","ask"]},{id:"correctness-over-quick-wins",name:"Correctness Over Quick Wins",description:"Always takes the correct, more laborious path over the fast partial one.",category:"working-style",section:"Working style",bullets:['When a choice is framed as "quick win vs. the longer correct way", always take the correct, more laborious path — do not ask.',"Don't offer a fast-but-partial path as an option; pick the thorough, correct solution by default.","Optimize for the right outcome, not the shortest route to a partial one."],tags:["correctness","thorough","no-shortcuts"]},{id:"do-both-dont-choose",name:"Do Both, Don't Choose",description:"When the option is A, B, or both, always does both without asking.",category:"working-style",section:"Working style",bullets:['When the choice is "do A, do B, or do both", always do both A and B — do not ask which.',"Treat inclusive options as a signal to deliver the complete set, not to pick one.","Skip either/or questions when doing all the options is feasible; just do them all."],tags:["comprehensive","both","no-either-or"]},{id:"zero-trust-inputs",name:"Zero Trust Inputs",description:"Treats every external input as hostile until validated.",category:"security",section:"Security posture",bullets:["Validate and normalize every input crossing a trust boundary before use.","Never interpolate untrusted data into SQL, shell, HTML, or log format strings.","Reject malformed input at the edge rather than sanitizing deep in the stack."],tags:["zero-trust","validation"]},{id:"secret-handling",name:"Secret Handling",description:"Keeps credentials out of code, logs, and error messages.",category:"security",section:"Security posture",bullets:["Never write secrets, tokens, or keys into source, config, or test fixtures.","Load secrets only from environment variables or a secrets manager at runtime.","Redact credentials and PII from every log line and error message."],tags:["secrets","credentials"]},{id:"dependency-audit",name:"Dependency Audit",description:"Scrutinizes every new dependency before adding it.",category:"security",section:"Security posture",bullets:["Before adding a dependency, check its maintenance status, license, and recent CVEs.","Prefer the standard library over a third-party package when the gap is small.","Pin direct dependencies to exact versions and regenerate lockfiles deliberately."],tags:["dependencies","supply-chain"]},{id:"supply-chain-aware",name:"Supply Chain Aware",description:"Guards against compromised build and install pipelines.",category:"security",section:"Security posture",bullets:["Never run install scripts from untrusted registries without reviewing them.","Verify checksums or signatures for binaries and tarballs downloaded during build.","Treat postinstall hooks and git submodules as privileged code and review them."],tags:["supply-chain","build-security"]},{id:"least-privilege",name:"Least Privilege",description:"Grants only the minimum permissions needed for each task.",category:"security",section:"Security posture",bullets:["Default every role, token, and file permission to the narrowest scope that works.","Justify in a comment any permission broader than read-only on its own resource.","Prefer short-lived credentials over long-lived ones wherever the platform allows."],tags:["least-privilege","permissions"]},{id:"crypto-conservative",name:"Crypto Conservative",description:"Uses vetted crypto primitives and never invents new ones.",category:"security",section:"Security posture",bullets:["Use a high-level, audited crypto library; never hand-roll primitives or protocols.","Use authenticated encryption (AEAD) for any encrypted payload.","Never compare secrets with non-constant-time equality."],tags:["crypto","security"]},{id:"threat-model-first",name:"Threat Model First",description:"Names the attacker and assets before designing security controls.",category:"security",section:"Security posture",bullets:["Before adding a security control, name the attacker, their capabilities, and the asset.","Call out assumptions that, if broken, would invalidate the control.","Document threats in a short note next to the code that implements the defense."],tags:["threat-model","STRIDE"]},{id:"bdd-style",name:"BDD Style",description:"Names and structures tests in Given/When/Then form.",category:"testing",section:"Testing discipline",bullets:['Name tests in the form "it <observable behavior> when <condition>".',"Structure each test body as Given (setup), When (action), Then (assertion).","Write tests from the caller's perspective, not the implementation's."],tags:["bdd","gherkin"]},{id:"property-based-tests",name:"Property Tests",description:"Reaches for property-based tests when invariants are clear.",category:"testing",section:"Testing discipline",bullets:["When a function has clear invariants, write a property-based test alongside examples.","Express properties as universally quantified statements over generated inputs.","Shrink failures to a minimal counterexample and commit it as a regression test."],tags:["property","fuzz","quickcheck"]},{id:"integration-first",name:"Integration First",description:"Prioritizes tests that exercise real collaborators end-to-end.",category:"testing",section:"Testing discipline",bullets:["Cover each feature with at least one test that exercises real collaborators end-to-end.","Mock only at trust boundaries (network, filesystem, clock), not internal seams.","If a unit test would duplicate an integration test, delete the redundant one."],tags:["integration","e2e"]},{id:"coverage-mandate",name:"Coverage Mandate",description:"Enforces a concrete coverage floor on new code.",category:"testing",section:"Testing discipline",bullets:["Every new module ships with line coverage of 80% or higher.","Every bug fix includes a test that fails before the fix and passes after.","Never lower a coverage threshold to make CI pass; raise tests instead."],tags:["coverage","ci"]},{id:"test-isolation",name:"Test Isolation",description:"Keeps every test independent, deterministic, and parallel-safe.",category:"testing",section:"Testing discipline",bullets:["Each test must pass in isolation and in any order, without shared mutable state.","Never use sleeps for synchronization; poll on an observable condition with a timeout.","Seed randomness and freeze the clock so failures are reproducible."],tags:["isolation","flaky","determinism"]},{id:"no-mocks-of-owned-code",name:"No Mocks Of Owned Code",description:"Avoids mocking code you control; uses real objects instead.",category:"testing",section:"Testing discipline",bullets:["Do not mock types you own; instantiate them with real data.","Mock only at the boundary to third-party services or slow resources.","If a class is painful to construct in a test, fix its constructor instead of mocking it."],tags:["mocks","london-vs-chicago"]},{id:"snapshot-tests-sparingly",name:"Snapshots Sparingly",description:"Uses snapshot tests only where the output is stable and meaningful.",category:"testing",section:"Testing discipline",bullets:["Prefer explicit assertions over snapshot tests for logic and data transformations.","Use snapshots only for large stable outputs (rendered HTML, CLI help text).","Review every snapshot diff manually; never update snapshots blindly."],tags:["snapshot","assertions"]},{id:"review-nitpicker",name:"Review Nitpicker",description:"Flags every issue including style, naming, and typos.",category:"review",section:"Code review",bullets:["In review, surface every issue you notice, including typos and naming.","Mark each comment as blocking, suggestion, or nit so the author can triage.","Propose a concrete alternative for every nit you raise."],tags:["nitpick","thorough-review"]},{id:"review-architecture-only",name:"Architecture Review",description:"Comments only on structure, boundaries, and contracts.",category:"review",section:"Code review",bullets:["In review, comment only on structure, boundaries, and contracts, not style.","Focus on module coupling, dependency direction, and data ownership.","Defer style and naming issues to linters and formatters."],tags:["architecture","high-level"]},{id:"review-security-focus",name:"Security Review",description:"Reviews changes through an attacker's lens.",category:"review",section:"Code review",bullets:["Scan every diff for injection, auth bypass, SSRF, and deserialization risks.","Flag any new trust boundary crossing and verify its validation.","Confirm secrets, PII, and tokens are not exposed in logs, errors, or telemetry."],tags:["security-review","audit"]},{id:"review-performance-focus",name:"Performance Review",description:"Looks for hot paths, allocations, and N+1 issues in review.",category:"review",section:"Code review",bullets:["Identify any new loop over external calls and flag potential N+1 patterns.","Note algorithmic complexity changes in hot paths.","Call out unnecessary allocations, copies, and redundant serialization."],tags:["performance-review"]},{id:"review-style-agnostic",name:"Style Agnostic",description:"Defers all style questions to the configured formatter.",category:"review",section:"Code review",bullets:["Never debate formatting or style; defer entirely to the configured formatter and linter.","If a style rule is missing, add it to config instead of arguing in review.","Focus review energy on behavior, correctness, and design."],tags:["style","formatter"]},{id:"review-ask-questions",name:"Review By Question",description:"Frames review comments as questions to invite dialogue.",category:"review",section:"Code review",bullets:["Phrase non-blocking feedback as a question that invites the author's reasoning.","Reserve imperative language for actual blockers.","Assume the author has context you lack until proven otherwise."],tags:["questions","collaborative-review"]},{id:"docs-minimal",name:"Minimal Docs",description:"Writes only the docs that explain non-obvious decisions.",category:"documentation",section:"Documentation",bullets:["Document the why, never the what; the code shows the what.","Skip docstrings on self-explanatory functions and trivial types.",'Write a short comment only where a reader would otherwise ask "why?".'],tags:["minimal-docs","why-not-what"]},{id:"docs-thorough",name:"Thorough Docs",description:"Documents every public symbol with intent, params, and examples.",category:"documentation",section:"Documentation",bullets:["Every exported function, type, and module has a docstring describing intent and contract.","Document parameters, return values, errors, and side effects explicitly.","Include a runnable example for any non-trivial public API."],tags:["thorough-docs","docstrings"]},{id:"examples-required",name:"Examples Required",description:"Pairs every public API with at least one runnable example.",category:"documentation",section:"Documentation",bullets:["Ship every public API with at least one runnable usage example.","Keep examples short, self-contained, and executable in isolation.","Verify examples in CI so they never drift from the code."],tags:["examples","usage"]},{id:"adr-first",name:"ADR First",description:"Captures architecture decisions as numbered records.",category:"documentation",section:"Documentation",bullets:["For any decision with long-term impact, write an ADR before implementing.","State the context, alternatives, decision, and consequences in the ADR.","Number ADRs sequentially and never delete them; supersede instead."],tags:["adr","architecture-decisions"]},{id:"changelog-discipline",name:"Changelog Discipline",description:"Updates the changelog with every user-visible change.",category:"documentation",section:"Documentation",bullets:["Add a changelog entry for every user-visible change in the same commit.","Group entries under Added, Changed, Deprecated, Removed, Fixed, Security.","Write entries from the user's perspective, not the implementer's."],tags:["changelog","keep-a-changelog"]},{id:"inline-comments-only",name:"Inline Comments Only",description:"Keeps documentation next to the code it describes.",category:"documentation",section:"Documentation",bullets:["Prefer inline comments and docstrings over separate markdown documentation.","When external docs are needed, generate them from the inline sources.","Never let external docs contradict the code; delete them if they drift."],tags:["inline","single-source"]},{id:"hypothesis-driven-debug",name:"Hypothesis Driven",description:"Debugs by stating and testing explicit hypotheses.",category:"debugging",section:"Debugging approach",bullets:["State an explicit hypothesis before each debugging action.","Describe what observation would confirm or refute the hypothesis.","If three hypotheses fail, stop and re-examine your assumptions from scratch."],tags:["hypothesis","scientific-debugging"]},{id:"binary-search-debug",name:"Binary Search Debug",description:"Narrows down bugs by bisecting code, commits, or inputs.",category:"debugging",section:"Debugging approach",bullets:["When a bug was recently introduced, bisect commits to find the offender.","When a bug is in a long pipeline, halve the input or code path until it localizes.","Record each bisection step so the path to the root cause is reproducible."],tags:["bisect","binary-search"]},{id:"log-first-debug",name:"Log First Debug",description:"Adds structured logs before reaching for a debugger.",category:"debugging",section:"Debugging approach",bullets:["Add structured logs at decision points before stepping through with a debugger.","Log the inputs, outputs, and branch taken at each suspect boundary.","Remove or downgrade debug logs before merging."],tags:["logging","tracing"]},{id:"reproduce-first",name:"Reproduce First",description:"Gets a reliable reproduction before attempting any fix.",category:"debugging",section:"Debugging approach",bullets:["Never attempt a fix until you can reproduce the bug on demand.","Capture the reproduction as a failing test before changing production code.","If the bug cannot be reproduced, instrument the system until it can."],tags:["repro","regression-test"]},{id:"five-whys",name:"Five Whys",description:"Drills past the first symptom to the root cause.",category:"debugging",section:"Debugging approach",bullets:['For every bug, ask "why" at least five times to reach a root cause, not a symptom.',"Record the chain of causes in the commit or PR description.","Fix the deepest cause that is economical to address, not the surface symptom."],tags:["root-cause","five-whys"]},{id:"yagni",name:"YAGNI",description:"Builds only what is needed right now.",category:"architecture",section:"Architecture",bullets:["Implement only the behavior required by a current, concrete caller.","Delete dead code, unused parameters, and speculative abstractions on sight.","Never add configuration until a second caller needs a different value."],tags:["yagni","simplicity"]},{id:"dry-with-care",name:"DRY With Care",description:"Deduplicates only when duplication represents the same idea.",category:"architecture",section:"Architecture",bullets:["Extract a helper only after seeing the same logic represent the same concept three times.","Prefer duplication over the wrong abstraction.","When deduplicating, name the concept the new helper represents."],tags:["dry","rule-of-three"]},{id:"solid-strict",name:"SOLID Strict",description:"Applies SOLID principles rigorously to OO designs.",category:"architecture",section:"Architecture",bullets:["Each class has one reason to change; split classes that mix responsibilities.","Depend on abstractions at module boundaries, not concrete implementations.","Clients should never be forced to depend on methods they do not use."],tags:["solid","oop"]},{id:"functional-core",name:"Functional Core",description:"Keeps pure logic at the core and side effects at the edge.",category:"architecture",section:"Architecture",bullets:["Keep business logic pure: no I/O, no clocks, no randomness in core functions.","Push side effects to a thin imperative shell that calls the pure core.","Pass data in and out explicitly; avoid hidden mutable state."],tags:["functional-core","imperative-shell"]},{id:"hexagonal-architecture",name:"Hexagonal",description:"Organizes code around ports and adapters.",category:"architecture",section:"Architecture",bullets:["Define ports (interfaces) for every external dependency the domain needs.","Place adapters at the boundary; domain code never imports infrastructure.","Test the domain through ports, swapping in fakes for adapters."],tags:["hexagonal","ports-adapters"]},{id:"event-driven",name:"Event Driven",description:"Models state changes as immutable events.",category:"architecture",section:"Architecture",bullets:["Represent state changes as named, immutable events rather than in-place mutations.","Derive current state by folding over events; never lose history.","Publish events at module boundaries so consumers can react without coupling."],tags:["events","cqrs","event-sourcing"]},{id:"composition-over-inheritance",name:"Composition Over Inheritance",description:"Reaches for composition before class hierarchies.",category:"architecture",section:"Architecture",bullets:["Reach for composition and interfaces before subclassing.","Use inheritance only for true is-a relationships with stable contracts.","Never extend a class just to reuse a few of its methods."],tags:["composition","inheritance"]},{id:"boy-scout",name:"Boy Scout Rule",description:"Leaves every file a little cleaner than you found it.",category:"refactoring",section:"Refactoring",bullets:["Leave every file you touch at least slightly cleaner than you found it.","Fix bad names, dead code, and misleading comments when you pass through them.","Keep cleanup scoped to what you touched; do not sprawl."],tags:["boy-scout","continuous-cleanup"]},{id:"preserve-behavior",name:"Preserve Behavior",description:"Refactors without changing observable behavior.",category:"refactoring",section:"Refactoring",bullets:["When refactoring, do not change observable behavior or tests in the same commit.","Run the full test suite before and after each refactoring step.","If a test needs to change, that is a behavior change; split it into its own commit."],tags:["refactor","safe-refactor"]},{id:"separate-refactor-commits",name:"Separate Refactor Commits",description:"Splits refactors and behavior changes into distinct commits.",category:"refactoring",section:"Refactoring",bullets:["Never mix a refactor with a behavior change in the same commit.",'Name refactor commits with a "refactor:" prefix so reviewers can skim them.',"When tempted to refactor mid-fix, stash, commit the refactor first, then resume."],tags:["commit-hygiene","refactor"]},{id:"extract-then-inline",name:"Extract Then Inline",description:"Uses extract and inline as the primary refactoring moves.",category:"refactoring",section:"Refactoring",bullets:["To understand tangled code, extract pieces into named helpers until structure emerges.","Once structure is clear, inline helpers that no longer earn their name.","Let naming drive the structure, not the other way around."],tags:["extract","inline","naming"]},{id:"rename-aggressively",name:"Rename Aggressively",description:"Renames as soon as a better name appears.",category:"refactoring",section:"Refactoring",bullets:["Rename a symbol the moment you think of a clearer name.","Names should describe intent and units, not implementation.","Commit renames separately so diffs stay reviewable."],tags:["rename","naming"]},{id:"measure-first",name:"Measure First",description:"Profiles before optimizing anything.",category:"performance",section:"Performance",bullets:["Never optimize without a profile or benchmark identifying the hot path.","Record a baseline measurement before any performance change.","Reject performance claims that are not backed by numbers."],tags:["profile","benchmark"]},{id:"big-o-aware",name:"Big-O Aware",description:"States and checks algorithmic complexity for data-heavy code.",category:"performance",section:"Performance",bullets:["State the time and space complexity of any non-trivial algorithm in a comment.","Flag any nested loop over user-scaled data as a complexity hazard.","Prefer O(n) solutions over O(n log n) only when n is provably small or constant."],tags:["complexity","big-o"]},{id:"avoid-premature-opt",name:"Avoid Premature Optimization",description:"Writes clear code first and optimizes only when required.",category:"performance",section:"Performance",bullets:["Write the clearest correct solution first; optimize only against a measured target.","Never trade readability for speed without a benchmark showing the trade is worth it.","Document any non-obvious optimization with the benchmark that justified it."],tags:["premature-optimization","clarity"]},{id:"allocation-conscious",name:"Allocation Conscious",description:"Minimizes unnecessary allocations on hot paths.",category:"performance",section:"Performance",bullets:["On hot paths, preallocate buffers and reuse them across iterations.","Avoid constructing intermediate collections just to transform them.","Prefer streaming and iterators over materializing entire datasets."],tags:["allocations","gc"]},{id:"cache-aware",name:"Cache Aware",description:"Considers locality and cache behavior in hot code.",category:"performance",section:"Performance",bullets:["Lay out hot data contiguously and traverse it in memory order.","Prefer arrays of structs or structs of arrays based on actual access patterns.","Avoid pointer-chasing in inner loops on large datasets."],tags:["cache","locality"]},{id:"latency-budget",name:"Latency Budget",description:"Designs against explicit per-request latency budgets.",category:"performance",section:"Performance",bullets:["State a latency budget for each request path and allocate it across stages.","Measure p50, p95, and p99 latencies, not just averages.","Reject any change that silently blows the budget at p95."],tags:["latency","slo"]},{id:"pair-mode",name:"Pair Mode",description:"Acts as an engaged pair-programming partner.",category:"collaboration",section:"Collaboration",bullets:["Narrate your reasoning as you go, as a pair partner would.","Before typing, state what you intend to do and why.","Pause at natural checkpoints and invite the user to drive or object."],tags:["pair","pairing"]},{id:"async-friendly",name:"Async Friendly",description:"Produces self-contained written artifacts for async review.",category:"collaboration",section:"Collaboration",bullets:["Summarize every session with a written handoff another engineer could resume from.","Include open questions, known gotchas, and next steps in every summary.","Never assume synchronous follow-up; write as if the reader is in another timezone."],tags:["async","remote"]},{id:"pr-discipline",name:"PR Discipline",description:"Keeps pull requests small, focused, and well-described.",category:"collaboration",section:"Collaboration",bullets:["Keep each PR under ~400 lines of diff where possible; split larger work.","Every PR has one purpose stated in its title and described in its body.","PR descriptions explain motivation, approach, and testing performed."],tags:["pr","pull-request"]},{id:"commit-hygiene",name:"Commit Hygiene",description:"Crafts atomic commits with well-formed messages.",category:"collaboration",section:"Collaboration",bullets:["Each commit is atomic: one logical change that leaves the tree green.","Write commit messages with a 50-char imperative subject and a wrapped body explaining why.","Use conventional prefixes (feat, fix, refactor, docs, test, chore) consistently."],tags:["commits","conventional-commits"]},{id:"handoff-notes",name:"Handoff Notes",description:"Ends every session with a structured handoff note.",category:"collaboration",section:"Collaboration",bullets:["End each session with a handoff note listing what changed, what is pending, and what is blocked.","List every file touched and why in the handoff.","Capture commands needed to resume work in a runnable form."],tags:["handoff","session-summary"]},{id:"conflict-surface",name:"Surface Conflicts",description:"Raises disagreements early rather than working around them.",category:"collaboration",section:"Collaboration",bullets:["When you disagree with a request, state the disagreement and your reasoning once.","After stating your concern, proceed with the user's decision unless it risks harm.","Never silently sandbag a task you disagree with."],tags:["disagree-and-commit"]},{id:"rust-idiomatic",name:"Rust Idiomatic",description:"Follows canonical Rust ownership and error conventions.",category:"domain",section:"Language idioms",bullets:["Model errors with enums and the `?` operator; never use `unwrap` in library code.","Accept borrowed slices (`&str`, `&[T]`) in function signatures where ownership is not needed.","Use iterators and combinators over explicit index loops.","Run `cargo clippy` and address every lint before declaring work done."],tags:["rust","clippy"]},{id:"ts-strict",name:"TypeScript Strict",description:"Relies on the strictest TypeScript settings and narrow types.",category:"domain",section:"Language idioms",bullets:["Enable `strict`, `noUncheckedIndexedAccess`, and `exactOptionalPropertyTypes`.","Never use `any`; use `unknown` with narrowing or generics instead.","Prefer discriminated unions over optional fields for state modeling.","Type function boundaries explicitly; let inference handle locals."],tags:["typescript","strict"]},{id:"react-hooks-rules",name:"React Hooks Rules",description:"Follows the rules of hooks and modern React patterns.",category:"domain",section:"Framework conventions",bullets:["Call hooks only at the top level of components and custom hooks, never conditionally.","Include every reactive value in effect dependency arrays; never suppress the lint.","Derive state during render where possible; reach for `useState` only for true state.","Extract reusable stateful logic into custom hooks named `use*`."],tags:["react","hooks"]},{id:"python-typed",name:"Python Typed",description:"Writes fully type-annotated, mypy-clean Python.",category:"domain",section:"Language idioms",bullets:["Annotate every function signature and public attribute with types.","Run `mypy --strict` (or equivalent) and fix every error.","Prefer `dataclass` or `pydantic` models over untyped dicts for structured data.","Use `Protocol` for structural typing instead of inheritance-based interfaces."],tags:["python","mypy","typing"]},{id:"go-idioms",name:"Go Idioms",description:"Follows idiomatic Go for errors, concurrency, and style.",category:"domain",section:"Language idioms",bullets:['Return errors explicitly and wrap with context via `fmt.Errorf("...: %w", err)`.',"Accept interfaces, return concrete types.","Pass `context.Context` as the first argument to any function that blocks or does I/O.","Run `go vet` and `staticcheck` and address every finding."],tags:["go","golang"]},{id:"sql-safe",name:"SQL Safe",description:"Writes parameterized, explicit, index-aware SQL.",category:"domain",section:"Database conventions",bullets:["Always use parameterized queries; never interpolate values into SQL strings.","List columns explicitly in `SELECT` and `INSERT`; never use `SELECT *` in production code.","Check the query plan for any new query touching a large table.","Wrap multi-statement writes in an explicit transaction."],tags:["sql","database"]},{id:"k8s-aware",name:"Kubernetes Aware",description:"Writes Kubernetes manifests that are safe and production-ready.",category:"domain",section:"Infrastructure conventions",bullets:["Set resource `requests` and `limits` on every container.","Define readiness and liveness probes for every workload.","Run containers as non-root with a read-only root filesystem where feasible.","Pin images by digest, not tag, for reproducible deploys."],tags:["kubernetes","k8s","devops"]},{id:"twelve-factor",name:"Twelve Factor",description:"Follows twelve-factor principles for services.",category:"domain",section:"Infrastructure conventions",bullets:["Read all configuration from environment variables, never from files baked into the image.","Treat logs as event streams written to stdout; never write log files from the app.","Design processes to be stateless and disposable; persist state in backing services."],tags:["twelve-factor","cloud-native"]},{id:"accessibility-first",name:"Accessibility First",description:"Treats a11y as a baseline requirement for every UI change.",category:"domain",section:"Frontend conventions",bullets:["Use semantic HTML elements before reaching for ARIA.","Ensure every interactive element is reachable and operable by keyboard.","Provide accessible names for icons, buttons, and form controls.","Verify color contrast meets WCAG AA for all text."],tags:["a11y","accessibility","wcag"]},{id:"i18n-aware",name:"Internationalization Aware",description:"Keeps user-facing strings externalized and locale-safe.",category:"domain",section:"Frontend conventions",bullets:["Never hardcode user-facing strings; route them through the i18n layer.","Format dates, numbers, and currencies through locale-aware APIs.","Avoid string concatenation for sentences; use interpolation with named placeholders."],tags:["i18n","l10n"]},{id:"observability-minded",name:"Observability Minded",description:"Instruments code with logs, metrics, and traces by default.",category:"architecture",section:"Observability",bullets:["Emit a structured log with correlation id at every service boundary.","Add a metric for every operation whose rate, latency, or error count matters.","Propagate trace context across async boundaries and external calls."],tags:["observability","telemetry"]},{id:"feature-flag-rollouts",name:"Feature Flag Rollouts",description:"Ships risky changes behind flags with a rollback plan.",category:"working-style",section:"Working style",bullets:["Put any risky or user-visible change behind a feature flag by default.","Document the rollout and rollback plan in the PR description.","Remove flags promptly once the change is fully rolled out."],tags:["feature-flags","rollout"]},{id:"backwards-compatible",name:"Backwards Compatible",description:"Treats public interfaces as contracts that cannot silently break.",category:"architecture",section:"Architecture",bullets:["Never change the shape of a public API without a deprecation path.","Add new optional fields rather than renaming or removing existing ones.","Version any breaking change and keep the old version running until consumers migrate."],tags:["compat","versioning"]},{id:"error-handling-explicit",name:"Explicit Errors",description:"Treats error paths as first-class, not afterthoughts.",category:"architecture",section:"Error handling",bullets:["Name every error condition; never swallow exceptions silently.","Attach enough context to each error for a reader to diagnose without a debugger.","Distinguish expected failures (return them) from bugs (raise/panic)."],tags:["errors","exceptions"]},{id:"idempotency",name:"Idempotent Operations",description:"Designs write operations to be safely retryable.",category:"architecture",section:"Architecture",bullets:["Make every external write operation idempotent or protected by an idempotency key.","Never assume a network call succeeded just because the request was sent.","Design retries with exponential backoff and a cap on attempts."],tags:["idempotency","retries"]},{id:"null-safety",name:"Null Safety",description:"Makes the absence of values explicit in the type system.",category:"architecture",section:"Architecture",bullets:["Represent optional values with `Option`/`Maybe`/`| null` explicitly in types.","Handle the absent case at the boundary, not deep in business logic.","Never use null as a sentinel for error or default."],tags:["null","optional"]},{id:"migration-safety",name:"Migration Safety",description:"Writes database migrations that are reversible and online-safe.",category:"domain",section:"Database conventions",bullets:["Make every migration safe to run while the old code is still live.","Expand-then-contract: add new columns, backfill, switch reads, then drop old ones.","Provide a tested down-migration for every up-migration."],tags:["migrations","schema"]},{id:"concurrency-careful",name:"Concurrency Careful",description:"Treats shared mutable state as a serious hazard.",category:"architecture",section:"Concurrency",bullets:["Prefer message passing or immutable data over shared mutable state.","Document the locking order for every mutex to prevent deadlocks.","Never hold a lock across I/O or an await point."],tags:["concurrency","threads","async"]},{id:"contract-tests",name:"Contract Tests",description:"Verifies assumptions at every service boundary.",category:"testing",section:"Testing discipline",bullets:["For every external service you depend on, write a contract test that pins its observed behavior.","Run contract tests against a real or high-fidelity fake of the dependency.","Fail loudly when a contract drifts; do not paper over it in the client."],tags:["contract-tests","boundaries"]},{id:"deprecation-discipline",name:"Deprecation Discipline",description:"Removes dead and deprecated code on a schedule.",category:"refactoring",section:"Refactoring",bullets:["Mark deprecated APIs with a clear annotation and a removal date.","When adding a replacement, update all internal callers in the same change.","Delete deprecated code once the removal date passes; do not let it linger."],tags:["deprecation","cleanup"]},{id:"defensive-assertions",name:"Defensive Assertions",description:"Encodes invariants as runtime assertions at trust boundaries.",category:"architecture",section:"Architecture",bullets:["Assert invariants at the entry of public functions to fail fast on violations.","Prefer assertions that describe the violated invariant in plain language.","Never use assertions for user-input validation; use real error returns there."],tags:["assertions","invariants","fail-fast"]}],U=/<[A-Za-z][A-Za-z0-9_-]*>/g,K=/<[A-Za-z][A-Za-z0-9_-]*>/;function H(t){return t.match(U)??[]}function Q(t){const n=[],r=(a,c)=>{if(typeof a=="string")for(const o of H(a))n.push({token:o,label:c})};r(t.command,"command");const s=Array.isArray(t.args)?t.args:[];s.forEach((a,c)=>{if(typeof a!="string")return;const o=s[c-1],i=c>0&&typeof o=="string"&&o.startsWith("-")&&!K.test(o)?`${o} ${a}`:a;r(a,i)});for(const[a,c]of Object.entries(t.env??{}))r(c,`env ${a}`);return r(t.url,"url"),n}function J(t){const n=new Map;for(const r of Q(t))n.has(r.token)||n.set(r.token,r);return[...n.values()]}function Y(t,n){const r=a=>a.replace(U,c=>Object.prototype.hasOwnProperty.call(n,c)?n[c]:c),s={...t};return typeof s.command=="string"&&(s.command=r(s.command)),Array.isArray(s.args)&&(s.args=s.args.map(a=>typeof a=="string"?r(a):a)),s.env&&(s.env=Object.fromEntries(Object.entries(s.env).map(([a,c])=>[a,typeof c=="string"?r(c):c]))),typeof s.url=="string"&&(s.url=r(s.url)),s}const $=/<!--\s*claude-presets:start(?:\s+id=([^>]*?))?\s*-->/,E="<!-- claude-presets:end -->";function W(t){const n=t.match($);if(!n)return[];const r=(n[1]??"").trim();return r?r.split(",").map(s=>s.trim()).filter(Boolean):[]}function X(t){if(t.length===0)return`<!-- claude-presets:start -->
15
+ <!-- claude-presets:end -->`;const n=[],r=new Map;for(const c of t){const o=c.section.trim().toLowerCase();let i=r.get(o);i===void 0&&(i=n.length,r.set(o,i),n.push({section:c.section.trim(),bullets:[]})),n[i].bullets.push(...c.bullets)}const s=n.map(c=>`# ${c.section}
16
16
 
17
- ${u.bullets.map(r=>`- ${r.trim()}`).join(`
17
+ ${c.bullets.map(o=>`- ${o.trim()}`).join(`
18
18
  `)}`).join(`
19
19
 
20
- `);return`<!-- claude-presets:start id=${t.map(u=>u.id).join(",")} -->
21
- ${n}
22
- <!-- claude-presets:end -->`}function V(t,o){const l=U(o),n=t.match(B);if(n&&n.index!==void 0){const d=n.index,u=t.indexOf(E,d);if(u>=0){const r=t.slice(0,d),i=t.slice(u+E.length),h=r.replace(/\s*$/,""),c=i.replace(/^\s*/,"");return`${h}${h?`
20
+ `);return`<!-- claude-presets:start id=${t.map(c=>c.id).join(",")} -->
21
+ ${s}
22
+ <!-- claude-presets:end -->`}function Z(t,n){const r=X(n),s=t.match($);if(s&&s.index!==void 0){const a=s.index,c=t.indexOf(E,a);if(c>=0){const o=t.slice(0,a),i=t.slice(c+E.length),f=o.replace(/\s*$/,""),u=i.replace(/^\s*/,"");return`${f}${f?`
23
23
 
24
- `:""}${l}${c?`
24
+ `:""}${r}${u?`
25
25
 
26
26
  `:`
27
- `}${c}`}}return t.trim()?`${l}
27
+ `}${u}`}}return t.trim()?`${r}
28
28
 
29
- ${t.replace(/^\s+/,"")}`:l+`
30
- `}function K(t,o,l){const n=$(t),d=n.includes(o)?n.filter(i=>i!==o):[...n,o],u=new Map(l.map(i=>[i.id,i])),r=d.map(i=>u.get(i)).filter(i=>i!==void 0);return V(t,r)}function H(t,o){let l=t;const n=l.match(B);if(n&&n.index!==void 0){const r=l.indexOf(E,n.index);r>=0&&(l=l.slice(0,n.index)+l.slice(r+E.length))}const d=new Set(o.map(r=>r.section.trim().toLowerCase())),u=new Set;for(const r of l.split(`
31
- `)){const i=r.match(/^#\s+(.+?)\s*$/);if(!i)continue;const h=i[1].trim();d.has(h.toLowerCase())&&u.add(h)}return Array.from(u)}function Q(t,o){if(o.length===0)return t;const l=new Set(o.map(c=>c.trim().toLowerCase())),n=t.match(B);let d=t,u="",r="";if(n&&n.index!==void 0){const c=t.indexOf(E,n.index);c>=0&&(d=t.slice(0,n.index),u=t.slice(n.index,c+E.length),r=t.slice(c+E.length))}const i=c=>{const y=c.split(`
32
- `),g=[];let p=!1;for(const v of y){const x=v.match(/^#\s+(.+?)\s*$/);if(x){if(p=l.has(x[1].trim().toLowerCase()),p)continue}else if(p)continue;g.push(v)}return g.join(`
29
+ ${t.replace(/^\s+/,"")}`:r+`
30
+ `}function ee(t,n,r){const s=W(t),a=s.includes(n)?s.filter(i=>i!==n):[...s,n],c=new Map(r.map(i=>[i.id,i])),o=a.map(i=>c.get(i)).filter(i=>i!==void 0);return Z(t,o)}function te(t,n){let r=t;const s=r.match($);if(s&&s.index!==void 0){const o=r.indexOf(E,s.index);o>=0&&(r=r.slice(0,s.index)+r.slice(o+E.length))}const a=new Set(n.map(o=>o.section.trim().toLowerCase())),c=new Set;for(const o of r.split(`
31
+ `)){const i=o.match(/^#\s+(.+?)\s*$/);if(!i)continue;const f=i[1].trim();a.has(f.toLowerCase())&&c.add(f)}return Array.from(c)}function ie(t,n){if(n.length===0)return t;const r=new Set(n.map(u=>u.trim().toLowerCase())),s=t.match($);let a=t,c="",o="";if(s&&s.index!==void 0){const u=t.indexOf(E,s.index);u>=0&&(a=t.slice(0,s.index),c=t.slice(s.index,u+E.length),o=t.slice(u+E.length))}const i=u=>{const y=u.split(`
32
+ `),m=[];let h=!1;for(const v of y){const S=v.match(/^#\s+(.+?)\s*$/);if(S){if(h=r.has(S[1].trim().toLowerCase()),h)continue}else if(h)continue;m.push(v)}return m.join(`
33
33
  `).replace(/\n{3,}/g,`
34
34
 
35
- `)},h=(u?i(d).replace(/\s*$/,"")+(d.trim()?`
35
+ `)},f=(c?i(a).replace(/\s*$/,"")+(a.trim()?`
36
36
 
37
- `:"")+u+(r.trim()?`
37
+ `:"")+c+(o.trim()?`
38
38
 
39
39
  `:`
40
- `)+i(r).replace(/^\s*/,""):i(d)).replace(/^\s*\n+/,"").replace(/\n{3,}/g,`
40
+ `)+i(o).replace(/^\s*/,""):i(a)).replace(/^\s*\n+/,"").replace(/\n{3,}/g,`
41
41
 
42
- `);return h.endsWith(`
43
- `)?h:h+`
44
- `}function J(t,o,l){const n=$(t);if(n.includes(o.id))return 0;const d=new Map(l.map(r=>[r.id,r])),u=o.section.trim().toLowerCase();return n.map(r=>d.get(r)).filter(r=>!!r).filter(r=>r.section.trim().toLowerCase()===u).length}function I(t,...o){if(!t.trim())return!0;const l=t.toLowerCase();return o.some(n=>n.toLowerCase().includes(l))}function se(){const t=D(),[o,l]=m.useState(new Set),[n,d]=m.useState(null),[u,r]=m.useState(null),[i,h]=m.useState(null),[c,y]=m.useState(""),g=async()=>{var b;if(!t)return;const s=((b=(await window.api.config.readJson(`${t}/.claude.json`)).data)==null?void 0:b.mcpServers)??{};l(new Set(Object.keys(s)))};m.useEffect(()=>{g()},[t]);const p=m.useMemo(()=>G.filter(a=>I(c,a.id,a.name,a.description)),[c]),v=async a=>{if(!t)return;d(a.id),r(null);const s=`${t}/.claude.json`,b=await window.api.config.readJson(s),k=(b.data&&typeof b.data=="object"?b.data:{})??{},w={...k.mcpServers??{}};w[a.id]={..."command"in a.config?{type:"stdio"}:{},...a.config};const C=await window.api.config.writeJson(s,{...k,mcpServers:w});if(d(null),!C.ok){r(C.error??"write failed");return}h(`installed ${a.id} — switch to Installed to edit placeholders`),setTimeout(()=>h(null),4e3),g()},x=async a=>{if(!t)return;d(a),r(null);const s=`${t}/.claude.json`,b=await window.api.config.readJson(s),k=(b.data&&typeof b.data=="object"?b.data:{})??{},w={...k.mcpServers??{}};delete w[a];const C=await window.api.config.writeJson(s,{...k,mcpServers:w});if(d(null),!C.ok){r(C.error??"write failed");return}g()};return t?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx(L,{query:c,onQueryChange:y,count:p.length,total:G.length}),(i||u)&&e.jsx("div",{className:`px-4 py-2 text-xs border-b border-line ${u?"text-red-400 bg-red-950/20":"text-accent bg-bg-elev"}`,children:u??i}),e.jsxs("div",{className:"flex-1 overflow-auto divide-y divide-line",children:[p.map(a=>{const s=o.has(a.id);return e.jsxs("div",{className:"px-4 py-3 flex items-start gap-3 hover:bg-bg-elev/50",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-fg text-xs font-medium",children:a.name}),a.official&&e.jsx(j,{children:"official"}),s&&e.jsx(j,{tone:"accent",children:"installed"}),a.envVars.length>0&&e.jsxs(j,{tone:"warn",children:[a.envVars.length," env"]})]}),e.jsx("div",{className:"text-fg-dim text-xs mt-0.5",children:a.description}),e.jsx("div",{className:"text-fg-faint text-[10px] font-mono mt-1 truncate",children:"command"in a.config?`${a.config.command} ${(a.config.args??[]).join(" ")}`:a.config.url})]}),e.jsxs("div",{className:"flex gap-1 shrink-0",children:[e.jsx(W,{href:a.homepage,children:"docs"}),s?e.jsx("button",{disabled:n===a.id,onClick:()=>x(a.id),className:"px-2 py-0.5 text-xs border border-line rounded text-fg-dim hover:text-red-400",children:"remove"}):e.jsx("button",{disabled:n===a.id,onClick:()=>v(a),className:"px-2 py-0.5 text-xs border border-accent rounded text-accent hover:bg-accent hover:text-bg",children:n===a.id?"…":"install"})]})]},a.id)}),p.length===0&&e.jsx(P,{title:"no matches"})]})]}):e.jsx(P,{title:"loading…"})}function ne(){const t=D(),[o,l]=m.useState(new Set),[n,d]=m.useState(""),u=async()=>{if(!t)return;const i=await window.api.config.listDir(`${t}/.claude/skills`,{dirsOnly:!0});l(new Set(i.entries.map(h=>h.name)))};m.useEffect(()=>{u()},[t]);const r=m.useMemo(()=>q.filter(i=>I(n,i.id,i.name,i.description)),[n]);return t?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx(L,{query:n,onQueryChange:d,count:r.length,total:q.length}),e.jsxs("div",{className:"flex-1 overflow-auto divide-y divide-line",children:[r.map(i=>{const h=o.has(i.id),c=i.source==="local",y=c?"":`mkdir -p ~/.claude/skills && cd ~/.claude/skills && git clone --depth 1 --filter=blob:none --sparse https://github.com/anthropics/skills _tmp-${i.id} && cd _tmp-${i.id} && git sparse-checkout set skills/${i.id} && mv skills/${i.id} ../${i.id} && cd .. && rm -rf _tmp-${i.id}`;return e.jsxs("div",{className:"px-4 py-3 flex items-start gap-3 hover:bg-bg-elev/50",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-fg text-xs font-medium",children:i.name}),i.official&&e.jsx(j,{children:"official"}),c&&e.jsx(j,{tone:"warn",children:"local"}),h&&e.jsx(j,{tone:"accent",children:"installed"})]}),e.jsx("div",{className:"text-fg-dim text-xs mt-0.5",children:i.description}),e.jsxs("div",{className:"text-fg-faint text-[10px] font-mono mt-1 truncate",children:["~/.claude/skills/",i.id,"/"]})]}),e.jsxs("div",{className:"flex gap-1 shrink-0",children:[!c&&e.jsx(W,{href:i.source,children:"source"}),!c&&e.jsx(_,{text:y,label:h?"reinstall cmd":"copy install"})]})]},i.id)}),r.length===0&&e.jsx(P,{title:"no matches"})]})]}):e.jsx(P,{title:"loading…"})}function ae(){const t=D(),[o,l]=m.useState(new Set),[n,d]=m.useState(""),u=async()=>{var c;if(!t)return;const i=new Set,h=await window.api.config.listDir(`${t}/.claude/plugins`,{dirsOnly:!0});for(const y of h.entries)i.add(y.name);try{const g=(c=(await window.api.config.readJson(`${t}/.claude/settings.json`)).data)==null?void 0:c.enabledPlugins;if(g)for(const[p,v]of Object.entries(g))v&&i.add(p.split("@")[0])}catch{}l(i)};m.useEffect(()=>{u()},[t]);const r=m.useMemo(()=>M.filter(i=>I(n,i.id,i.name,i.description)),[n]);return t?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx(L,{query:n,onQueryChange:d,count:r.length,total:M.length}),e.jsxs("div",{className:"flex-1 overflow-auto divide-y divide-line",children:[r.map(i=>{var p;const h=o.has(i.id),c=((p=i.marketplace)==null?void 0:p.name)??"anthropics/claude-plugins-official",y=`/plugin install ${i.id}@${c}`,g=i.marketplace&&i.marketplace.add!=="bundled"?`/plugin marketplace add ${i.marketplace.add}
45
- ${y}`:y;return e.jsxs("div",{className:"px-4 py-3 flex items-start gap-3 hover:bg-bg-elev/50",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-fg text-xs font-medium",children:i.name}),i.official&&e.jsx(j,{children:"official"}),h&&e.jsx(j,{tone:"accent",children:"installed"}),i.bundles.map(v=>e.jsx(j,{tone:"dim",children:v},v))]}),e.jsx("div",{className:"text-fg-dim text-xs mt-0.5",children:i.description}),e.jsx("div",{className:"text-fg-faint text-[10px] font-mono mt-1 truncate",children:y})]}),e.jsxs("div",{className:"flex gap-1 shrink-0 items-start",children:[e.jsx(W,{href:i.source,children:"source"}),e.jsx(_,{text:g,label:"copy"}),e.jsx(ee,{id:i.id,marketplace:i.marketplace,installed:h,onDone:u})]})]},i.id)}),r.length===0&&e.jsx(P,{title:"no matches"})]})]}):e.jsx(P,{title:"loading…"})}function Y(t,o){return(t[o.event]??[]).some(n=>(n.hooks??[]).some(d=>d.type==="command"&&d.command===o.command))}function oe(){const t=D(),[o,l]=m.useState({}),[n,d]=m.useState(null),[u,r]=m.useState(null),[i,h]=m.useState(null),[c,y]=m.useState(""),g=t?`${t}/.claude/settings.json`:null,p=async()=>{if(!g)return;const s=await window.api.config.readJson(g),b=(s.data&&typeof s.data=="object"?s.data:{})??{};l(b.hooks??{})};m.useEffect(()=>{p()},[g]);const v=m.useMemo(()=>F.filter(s=>I(c,s.id,s.name,s.description,s.event)),[c]),x=async s=>{if(!g)return;d(s.id),h(null);const b=await window.api.config.readJson(g),k=(b.data&&typeof b.data=="object"?b.data:{})??{},w={...k.hooks??{}},C=(w[s.event]??[]).slice();C.push({...s.matcher?{matcher:s.matcher}:{},hooks:[{type:"command",command:s.command,...s.timeout?{timeout:s.timeout}:{}}]}),w[s.event]=C;const f=await window.api.config.writeJson(g,{...k,hooks:w});if(d(null),!f.ok){h(f.error??"write failed");return}r(`installed ${s.id}`),setTimeout(()=>r(null),2500),p()},a=async s=>{if(!g)return;d(s.id),h(null);const b=await window.api.config.readJson(g),k=(b.data&&typeof b.data=="object"?b.data:{})??{},w={...k.hooks??{}},C=(w[s.event]??[]).map(S=>({...S,hooks:(S.hooks??[]).filter(N=>!(N.type==="command"&&N.command===s.command))})).filter(S=>(S.hooks??[]).length>0);C.length?w[s.event]=C:delete w[s.event];const f=await window.api.config.writeJson(g,{...k,hooks:w});if(d(null),!f.ok){h(f.error??"write failed");return}p()};return t?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx(L,{query:c,onQueryChange:y,count:v.length,total:F.length}),(u||i)&&e.jsx("div",{className:`px-4 py-2 text-xs border-b border-line ${i?"text-red-400 bg-red-950/20":"text-accent bg-bg-elev"}`,children:i??u}),e.jsxs("div",{className:"flex-1 overflow-auto divide-y divide-line",children:[v.map(s=>{const b=Y(o,s);return e.jsxs("div",{className:"px-4 py-3 flex items-start gap-3 hover:bg-bg-elev/50",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-fg text-xs font-medium",children:s.name}),e.jsx(j,{tone:"dim",children:s.event}),s.matcher&&e.jsxs(j,{tone:"dim",children:["match: ",s.matcher]}),b&&e.jsx(j,{tone:"accent",children:"installed"})]}),e.jsx("div",{className:"text-fg-dim text-xs mt-0.5",children:s.description}),e.jsx("div",{className:"text-fg-faint text-[10px] font-mono mt-1 truncate",children:s.command})]}),e.jsx("div",{className:"flex gap-1 shrink-0",children:b?e.jsx("button",{disabled:n===s.id,onClick:()=>a(s),className:"px-2 py-0.5 text-xs border border-line rounded text-fg-dim hover:text-red-400",children:"remove"}):e.jsx("button",{disabled:n===s.id,onClick:()=>x(s),className:"px-2 py-0.5 text-xs border border-accent rounded text-accent hover:bg-accent hover:text-bg",children:n===s.id?"…":"install"})})]},s.id)}),v.length===0&&e.jsx(P,{title:"no matches"})]})]}):e.jsx(P,{title:"loading…"})}function re(){const t=D(),[o,l]=m.useState(""),[n,d]=m.useState(null),[u,r]=m.useState(null),[i,h]=m.useState(null),[c,y]=m.useState(""),g=t?`${t}/.claude/settings.json`:null,p=async()=>{if(!g)return;const a=await window.api.config.readJson(g),s=(a.data&&typeof a.data=="object"?a.data:{})??{};l(JSON.stringify(s.permissions??{}))};m.useEffect(()=>{p()},[g]);const v=m.useMemo(()=>O.filter(a=>I(c,a.id,a.name,a.description)),[c]),x=async a=>{if(!g)return;d(a.id),h(null);const s=await window.api.config.readJson(g),b=(s.data&&typeof s.data=="object"?s.data:{})??{},k=await window.api.config.writeJson(g,{...b,permissions:a.permissions});if(d(null),!k.ok){h(k.error??"write failed");return}r(`applied ${a.id} — replaces existing permissions block`),setTimeout(()=>r(null),3e3),p()};return t?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx(L,{query:c,onQueryChange:y,count:v.length,total:O.length}),(u||i)&&e.jsx("div",{className:`px-4 py-2 text-xs border-b border-line ${i?"text-red-400 bg-red-950/20":"text-accent bg-bg-elev"}`,children:i??u}),e.jsxs("div",{className:"flex-1 overflow-auto divide-y divide-line",children:[v.map(a=>{const s=o===JSON.stringify(a.permissions),b=[];return a.permissions.allow&&b.push(`${a.permissions.allow.length} allow`),a.permissions.deny&&b.push(`${a.permissions.deny.length} deny`),a.permissions.ask&&b.push(`${a.permissions.ask.length} ask`),a.permissions.defaultMode&&b.push(`mode: ${a.permissions.defaultMode}`),e.jsxs("div",{className:"px-4 py-3 flex items-start gap-3 hover:bg-bg-elev/50",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-fg text-xs font-medium",children:a.name}),s&&e.jsx(j,{tone:"accent",children:"active"}),e.jsx(j,{tone:"warn",children:"replaces permissions"})]}),e.jsx("div",{className:"text-fg-dim text-xs mt-0.5",children:a.description}),e.jsx("div",{className:"text-fg-faint text-[10px] font-mono mt-1 truncate",children:b.join(" · ")})]}),e.jsx("div",{className:"flex gap-1 shrink-0",children:e.jsx("button",{disabled:n===a.id,onClick:()=>x(a),className:"px-2 py-0.5 text-xs border border-accent rounded text-accent hover:bg-accent hover:text-bg",children:n===a.id?"…":"apply"})})]},a.id)}),v.length===0&&e.jsx(P,{title:"no matches"})]})]}):e.jsx(P,{title:"loading…"})}const X={communication:"Communication","working-style":"Working style",security:"Security",testing:"Testing",review:"Code review",documentation:"Documentation",debugging:"Debugging",architecture:"Architecture",refactoring:"Refactoring",performance:"Performance",collaboration:"Collaboration",domain:"Domain / stack"};function ce(){const t=D(),[o,l]=m.useState(""),[n,d]=m.useState(null),[u,r]=m.useState(null),[i,h]=m.useState(null),[c,y]=m.useState(""),g=t?`${t}/.claude/CLAUDE.md`:null,p=async()=>{if(!g)return;const f=await window.api.config.readText(g);l(f.text)};m.useEffect(()=>{p()},[g]);const v=m.useMemo(()=>new Set($(o)),[o]),x=m.useMemo(()=>H(o,R),[o]),a=async()=>{if(!g||x.length===0)return;h(null);const f=Q(o,x),S=await window.api.config.writeText(g,f);if(!S.ok){h(S.error??"write failed");return}r(`removed ${x.length} unmanaged section(s)`),setTimeout(()=>r(null),3e3),p()},s=m.useMemo(()=>R.filter(f=>I(c,f.id,f.name,f.description,f.section,...f.tags??[])),[c]),b=m.useMemo(()=>{const f=new Map;for(const S of s){const N=f.get(S.category)??[];N.push(S),f.set(S.category,N)}return f},[s]),k=async f=>{if(!g)return;d(f.id),h(null);const S=K(o,f.id,R),N=await window.api.config.writeText(g,S);if(d(null),!N.ok){h(N.error??"write failed");return}const z=!v.has(f.id);r(z?`enabled "${f.name}"`:`disabled "${f.name}"`),setTimeout(()=>r(null),2500),p()};if(!t)return e.jsx(P,{title:"loading…"});const w=v.size,C=["communication","working-style","testing","review","security","debugging","architecture","refactoring","performance","documentation","collaboration","domain"];return e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{className:"shrink-0 border-b border-line bg-bg-elev px-3 py-1.5 flex items-center gap-2 text-xs",children:[e.jsx("span",{className:"text-fg-faint",children:w>0?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-fg-dim font-medium",children:w})," active · managed in"," ",e.jsx("code",{className:"text-fg-faint",children:"~/.claude/CLAUDE.md"})]}):e.jsx(e.Fragment,{children:"nothing active — toggle presets below to stack them in your CLAUDE.md"})}),e.jsx("div",{className:"flex-1"}),e.jsx("span",{className:"text-fg-faint",children:s.length===R.length?`${R.length} available`:`${s.length} of ${R.length}`}),e.jsx("input",{value:c,onChange:f=>y(f.target.value),placeholder:"search presets…",className:"bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg w-56"})]}),(u||i)&&e.jsx("div",{className:`px-4 py-2 text-xs border-b border-line ${i?"text-red-400 bg-red-950/20":"text-accent bg-bg-elev"}`,children:i??u}),x.length>0&&e.jsxs("div",{className:"px-4 py-2 text-xs border-b border-line bg-yellow-950/20 flex items-start gap-3",children:[e.jsxs("div",{className:"flex-1 text-yellow-500/90",children:[e.jsx("div",{className:"font-medium",children:"Your CLAUDE.md has unmanaged sections that will collide with presets:"}),e.jsx("div",{className:"text-yellow-500/70 mt-0.5",children:x.map(f=>`# ${f}`).join(" · ")}),e.jsx("div",{className:"text-fg-faint mt-1",children:"These were probably added before presets were toggleable. Clean them out so the managed block owns those sections."})]}),e.jsxs("button",{onClick:a,className:"shrink-0 px-3 py-1 text-xs border border-yellow-600/60 rounded text-yellow-400 hover:bg-yellow-600 hover:text-bg",children:["remove ",x.length," section",x.length>1?"s":""]})]}),e.jsxs("div",{className:"flex-1 overflow-auto",children:[C.map(f=>({cat:f,presets:b.get(f)??[]})).filter(f=>f.presets.length>0).map(({cat:f,presets:S})=>e.jsx(Z,{title:X[f],presets:S,activeIds:v,existing:o,busy:n,onToggle:k},f)),s.length===0&&e.jsx(P,{title:"no matches"})]})]})}function Z({title:t,presets:o,activeIds:l,existing:n,busy:d,onToggle:u}){const[r,i]=m.useState(!0),h=o.filter(c=>l.has(c.id)).length;return e.jsxs("section",{className:"border-b border-line",children:[e.jsxs("header",{className:"px-4 py-2 bg-bg-elev/40 cursor-pointer hover:bg-bg-elev flex items-center gap-3",onClick:()=>i(!r),children:[e.jsx("span",{className:"text-fg-faint w-3",children:r?"▾":"▸"}),e.jsx("h2",{className:"text-fg text-sm font-medium flex-1",children:t}),e.jsx("span",{className:"text-fg-faint text-xs",children:h>0?`${h}/${o.length} active`:`${o.length}`})]}),r&&e.jsx("div",{className:"divide-y divide-line/60",children:o.map(c=>{const y=l.has(c.id),g=J(n,c,R);return e.jsxs("div",{className:"px-4 py-3 flex items-start gap-3 hover:bg-bg-elev/20",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"text-fg text-sm",children:c.name}),y&&e.jsx(j,{tone:"accent",children:"active"}),e.jsxs("span",{className:"text-[10px] px-1 py-0 rounded border border-line bg-bg-elev text-fg-faint uppercase tracking-wide",children:["→ # ",c.section]}),!y&&g>0&&e.jsxs("span",{className:"text-[10px] px-1 py-0 rounded border border-yellow-900/40 bg-yellow-950/30 text-yellow-500/80 uppercase tracking-wide",children:["merges with ",g]})]}),e.jsx("div",{className:"text-fg-dim text-xs mt-0.5",children:c.description}),e.jsxs("ul",{className:"text-fg-faint text-[11px] mt-1 space-y-0.5 list-disc list-inside",children:[c.bullets.slice(0,2).map((p,v)=>e.jsx("li",{className:"truncate",children:p},v)),c.bullets.length>2&&e.jsxs("li",{className:"text-fg-faint italic",children:["+",c.bullets.length-2," more"]})]})]}),e.jsx("div",{className:"flex gap-1 shrink-0",children:e.jsx("button",{disabled:d===c.id,onClick:()=>u(c),className:`px-3 py-0.5 text-xs rounded border transition-colors ${y?"bg-accent text-bg border-accent hover:bg-transparent hover:text-fg-dim":"bg-bg-elev text-fg-dim border-line hover:text-fg hover:bg-bg-hi"}`,title:y?"remove from CLAUDE.md":"add to CLAUDE.md",children:d===c.id?"…":y?"on":"off"})})]},c.id)})})]})}function le({active:t,onChange:o,installedLabel:l="Installed",libraryLabel:n="Library"}){return e.jsx("div",{className:"flex rounded border border-line overflow-hidden",children:[["installed",l],["library",n]].map(([d,u])=>e.jsx("button",{onClick:()=>o(d),className:`px-2 py-0.5 text-xs ${t===d?"bg-bg-hi text-fg":"text-fg-dim hover:text-fg hover:bg-bg-hi"}`,children:u},d))})}function L({query:t,onQueryChange:o,count:l,total:n}){return e.jsxs("div",{className:"shrink-0 border-b border-line bg-bg-elev px-3 py-1.5 flex items-center gap-2 text-xs",children:[e.jsx("span",{className:"text-fg-faint",children:l===n?`${n} available`:`${l} of ${n}`}),e.jsx("div",{className:"flex-1"}),e.jsx("input",{value:t,onChange:d=>o(d.target.value),placeholder:"filter…",className:"bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg w-48"})]})}function W({href:t,children:o}){return e.jsx("a",{href:t,target:"_blank",rel:"noreferrer",className:"px-2 py-0.5 text-xs border border-line rounded text-fg-dim hover:text-fg hover:bg-bg-hi",children:o})}function ee({id:t,marketplace:o,installed:l,onDone:n}){const[d,u]=m.useState("idle"),[r,i]=m.useState([]),[h,c]=m.useState(!1),y=m.useRef(!0);m.useEffect(()=>()=>{y.current=!1},[]),m.useEffect(()=>{const p=window.api.plugins.onInstallProgress(({slug:v,line:x})=>{v===t&&i(a=>{const s=[...a,x];return s.length>200?s.slice(s.length-200):s})});return()=>p()},[t]);const g=async()=>{u("running"),i([]),c(!0);try{const p=await window.api.plugins.install({slug:t,marketplace:o});if(!y.current){p.ok?(T.info(`Installed ${t}`),n()):T.error(`Install failed: ${t} (exit ${p.exitCode})${p.error?` — ${p.error}`:""}`);return}p.ok?(u("idle"),T.info(`Installed ${t}`),n()):(u("error"),T.error(`Install failed: ${t} (exit ${p.exitCode})${p.error?` — ${p.error}`:""}`))}catch(p){if(!y.current){T.error(`Install error: ${t} — ${p instanceof Error?p.message:String(p)}`);return}u("error"),T.error(`Install error: ${t} — ${p instanceof Error?p.message:String(p)}`)}};return l?e.jsx("button",{disabled:!0,className:"px-2 py-0.5 text-xs border border-line rounded text-fg-faint bg-bg-elev cursor-default",children:"installed"}):e.jsxs("div",{className:"flex flex-col items-end gap-1",children:[e.jsx("button",{onClick:g,disabled:d==="running",className:`px-2 py-0.5 text-xs border rounded ${d==="running"?"border-line text-fg-faint bg-bg-elev cursor-not-allowed":"border-accent/50 text-accent hover:bg-accent hover:text-bg"}`,children:d==="running"?"installing…":d==="error"?"retry":"install"}),r.length>0&&e.jsx("button",{onClick:()=>c(p=>!p),className:"text-[10px] text-fg-faint hover:text-fg-dim",children:h?"hide log":"show log"}),h&&r.length>0&&e.jsx("pre",{className:"mt-0.5 max-h-40 w-72 overflow-auto bg-bg-elev border border-line rounded p-2 text-fg-faint font-mono text-[10px] whitespace-pre-wrap text-left",children:r.join(`
46
- `)})]})}function _({text:t,label:o}){const[l,n]=m.useState(!1);return e.jsx("button",{onClick:()=>{navigator.clipboard.writeText(t),n(!0),setTimeout(()=>n(!1),1500)},className:"px-2 py-0.5 text-xs border border-accent/50 rounded text-accent hover:bg-accent hover:text-bg",children:l?"copied!":o})}export{ie as C,oe as H,se as M,re as P,ne as S,le as V,F as a,G as b,M as c,q as d,ae as e,ce as f};
42
+ `);return f.endsWith(`
43
+ `)?f:f+`
44
+ `}function se(t,n,r){const s=W(t);if(s.includes(n.id))return 0;const a=new Map(r.map(o=>[o.id,o])),c=n.section.trim().toLowerCase();return s.map(o=>a.get(o)).filter(o=>!!o).filter(o=>o.section.trim().toLowerCase()===c).length}function I(t,...n){if(!t.trim())return!0;const r=t.toLowerCase();return n.some(s=>s.toLowerCase().includes(r))}function de(){const t=D(),[n,r]=g.useState(new Set),[s,a]=g.useState(null),[c,o]=g.useState(null),[i,f]=g.useState(null),[u,y]=g.useState(""),[m,h]=g.useState(null),v=async()=>{var j;if(!t)return;const x=((j=(await window.api.config.readJson(`${t}/.claude.json`)).data)==null?void 0:j.mcpServers)??{};r(new Set(Object.keys(x)))};g.useEffect(()=>{v()},[t]);const S=g.useMemo(()=>q.filter(d=>I(u,d.id,d.name,d.description)),[u]),b=d=>{const x=J(d.config);if(x.length>0){o(null),h({m:d,fields:x,values:{}});return}return l(d,d.config)},l=async(d,x)=>{if(!t)return;a(d.id),o(null);const j=`${t}/.claude.json`,p=await window.api.config.readJson(j),k=(p.data&&typeof p.data=="object"?p.data:{})??{},A={...k.mcpServers??{}};A[d.id]={..."command"in x?{type:"stdio"}:{},...x};const B=await window.api.config.writeJson(j,{...k,mcpServers:A});if(a(null),!B.ok){o(B.error??"write failed");return}h(null),f(`installed ${d.id}`),setTimeout(()=>f(null),4e3),v()},w=async d=>{if(!t)return;a(d),o(null);const x=`${t}/.claude.json`,j=await window.api.config.readJson(x),p=(j.data&&typeof j.data=="object"?j.data:{})??{},k={...p.mcpServers??{}};delete k[d];const A=await window.api.config.writeJson(x,{...p,mcpServers:k});if(a(null),!A.ok){o(A.error??"write failed");return}v()};return t?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx(L,{query:u,onQueryChange:y,count:S.length,total:q.length}),(i||c)&&e.jsx("div",{className:`px-4 py-2 text-xs border-b border-line ${c?"text-red-400 bg-red-950/20":"text-accent bg-bg-elev"}`,children:c??i}),m&&e.jsxs("div",{className:"px-4 py-3 border-b border-line bg-bg-elev space-y-2","data-testid":"mcp-placeholder-form",children:[e.jsxs("div",{className:"text-xs text-fg",children:["Configure ",e.jsx("span",{className:"font-medium",children:m.m.name})," — fill in every value before installing"]}),m.fields.map(d=>e.jsxs("label",{className:"flex items-center gap-2 text-xs",children:[e.jsx("span",{className:"w-64 shrink-0 text-fg-faint font-mono truncate",title:d.label,children:d.label}),e.jsx("input",{required:!0,"aria-label":d.token,value:m.values[d.token]??"",onChange:x=>{const j=x.target.value;h(p=>p&&{...p,values:{...p.values,[d.token]:j}})},placeholder:d.token,className:"flex-1 bg-bg border border-line rounded px-2 py-1 text-xs text-fg font-mono"})]},d.token)),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(O,{variant:"primary",disabled:s===m.m.id||m.fields.some(d=>!(m.values[d.token]??"").trim()),onClick:()=>l(m.m,Y(m.m.config,m.values)),children:"install"}),e.jsx(O,{onClick:()=>h(null),children:"cancel"})]})]}),e.jsxs("div",{className:"flex-1 overflow-auto divide-y divide-line",children:[S.map(d=>{const x=n.has(d.id);return e.jsxs("div",{className:"px-4 py-3 flex items-start gap-3 hover:bg-bg-elev/50",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-fg text-xs font-medium",children:d.name}),d.official&&e.jsx(C,{children:"official"}),x&&e.jsx(C,{tone:"accent",children:"installed"}),d.envVars.length>0&&e.jsxs(C,{tone:"warn",children:[d.envVars.length," env"]})]}),e.jsx("div",{className:"text-fg-dim text-xs mt-0.5",children:d.description}),e.jsx("div",{className:"text-fg-faint text-[10px] font-mono mt-1 truncate",children:"command"in d.config?`${d.config.command} ${(d.config.args??[]).join(" ")}`:d.config.url})]}),e.jsxs("div",{className:"flex gap-1 shrink-0",children:[e.jsx(G,{href:d.homepage,children:"docs"}),x?e.jsx("button",{disabled:s===d.id,onClick:()=>w(d.id),className:"px-2 py-0.5 text-xs border border-line rounded text-fg-dim hover:text-red-400",children:"remove"}):e.jsx("button",{disabled:s===d.id,onClick:()=>b(d),className:"px-2 py-0.5 text-xs border border-accent rounded text-accent hover:bg-accent hover:text-bg",children:s===d.id?"…":"install"})]})]},d.id)}),S.length===0&&e.jsx(N,{title:"no matches"})]})]}):e.jsx(N,{title:"loading…"})}function ue(){const t=D(),[n,r]=g.useState(new Set),[s,a]=g.useState(""),c=async()=>{if(!t)return;const i=await window.api.config.listDir(`${t}/.claude/skills`,{dirsOnly:!0});r(new Set(i.entries.map(f=>f.name)))};g.useEffect(()=>{c()},[t]);const o=g.useMemo(()=>M.filter(i=>I(s,i.id,i.name,i.description)),[s]);return t?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx(L,{query:s,onQueryChange:a,count:o.length,total:M.length}),e.jsxs("div",{className:"flex-1 overflow-auto divide-y divide-line",children:[o.map(i=>{const f=n.has(i.id),u=i.source==="local",y=u?"":`mkdir -p ~/.claude/skills && cd ~/.claude/skills && git clone --depth 1 --filter=blob:none --sparse https://github.com/anthropics/skills _tmp-${i.id} && cd _tmp-${i.id} && git sparse-checkout set skills/${i.id} && mv skills/${i.id} ../${i.id} && cd .. && rm -rf _tmp-${i.id}`;return e.jsxs("div",{className:"px-4 py-3 flex items-start gap-3 hover:bg-bg-elev/50",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-fg text-xs font-medium",children:i.name}),i.official&&e.jsx(C,{children:"official"}),u&&e.jsx(C,{tone:"warn",children:"local"}),f&&e.jsx(C,{tone:"accent",children:"installed"})]}),e.jsx("div",{className:"text-fg-dim text-xs mt-0.5",children:i.description}),e.jsxs("div",{className:"text-fg-faint text-[10px] font-mono mt-1 truncate",children:["~/.claude/skills/",i.id,"/"]})]}),e.jsxs("div",{className:"flex gap-1 shrink-0",children:[!u&&e.jsx(G,{href:i.source,children:"source"}),!u&&e.jsx(V,{text:y,label:f?"reinstall cmd":"copy install"})]})]},i.id)}),o.length===0&&e.jsx(N,{title:"no matches"})]})]}):e.jsx(N,{title:"loading…"})}function me(){const t=D(),[n,r]=g.useState(new Set),[s,a]=g.useState(""),c=async()=>{var u;if(!t)return;const i=new Set,f=await window.api.config.listDir(`${t}/.claude/plugins`,{dirsOnly:!0});for(const y of f.entries)i.add(y.name);try{const m=(u=(await window.api.config.readJson(`${t}/.claude/settings.json`)).data)==null?void 0:u.enabledPlugins;if(m)for(const[h,v]of Object.entries(m))v&&i.add(h.split("@")[0])}catch{}r(i)};g.useEffect(()=>{c()},[t]);const o=g.useMemo(()=>F.filter(i=>I(s,i.id,i.name,i.description)),[s]);return t?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx(L,{query:s,onQueryChange:a,count:o.length,total:F.length}),e.jsxs("div",{className:"flex-1 overflow-auto divide-y divide-line",children:[o.map(i=>{var h;const f=n.has(i.id),u=((h=i.marketplace)==null?void 0:h.name)??"anthropics/claude-plugins-official",y=`/plugin install ${i.id}@${u}`,m=i.marketplace&&i.marketplace.add!=="bundled"?`/plugin marketplace add ${i.marketplace.add}
45
+ ${y}`:y;return e.jsxs("div",{className:"px-4 py-3 flex items-start gap-3 hover:bg-bg-elev/50",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-fg text-xs font-medium",children:i.name}),i.official&&e.jsx(C,{children:"official"}),f&&e.jsx(C,{tone:"accent",children:"installed"}),i.bundles.map(v=>e.jsx(C,{tone:"dim",children:v},v))]}),e.jsx("div",{className:"text-fg-dim text-xs mt-0.5",children:i.description}),e.jsx("div",{className:"text-fg-faint text-[10px] font-mono mt-1 truncate",children:y})]}),e.jsxs("div",{className:"flex gap-1 shrink-0 items-start",children:[e.jsx(G,{href:i.source,children:"source"}),e.jsx(V,{text:m,label:"copy"}),e.jsx(re,{id:i.id,marketplace:i.marketplace,installed:f,onDone:c})]})]},i.id)}),o.length===0&&e.jsx(N,{title:"no matches"})]})]}):e.jsx(N,{title:"loading…"})}function ne(t,n){return(t[n.event]??[]).some(s=>(s.hooks??[]).some(a=>a.type==="command"&&a.command===n.command))}function pe(){const t=D(),[n,r]=g.useState({}),[s,a]=g.useState(null),[c,o]=g.useState(null),[i,f]=g.useState(null),[u,y]=g.useState(""),m=t?`${t}/.claude/settings.json`:null,h=async()=>{if(!m)return;const l=await window.api.config.readJson(m),w=(l.data&&typeof l.data=="object"?l.data:{})??{};r(w.hooks??{})};g.useEffect(()=>{h()},[m]);const v=g.useMemo(()=>_.filter(l=>I(u,l.id,l.name,l.description,l.event)),[u]),S=async l=>{if(!m)return;a(l.id),f(null);const w=await window.api.config.readJson(m),d=(w.data&&typeof w.data=="object"?w.data:{})??{},x={...d.hooks??{}},j=(x[l.event]??[]).slice();j.push({...l.matcher?{matcher:l.matcher}:{},hooks:[{type:"command",command:l.command,...l.timeout?{timeout:l.timeout}:{}}]}),x[l.event]=j;const p=await window.api.config.writeJson(m,{...d,hooks:x});if(a(null),!p.ok){f(p.error??"write failed");return}o(`installed ${l.id}`),setTimeout(()=>o(null),2500),h()},b=async l=>{if(!m)return;a(l.id),f(null);const w=await window.api.config.readJson(m),d=(w.data&&typeof w.data=="object"?w.data:{})??{},x={...d.hooks??{}},j=(x[l.event]??[]).map(k=>({...k,hooks:(k.hooks??[]).filter(A=>!(A.type==="command"&&A.command===l.command))})).filter(k=>(k.hooks??[]).length>0);j.length?x[l.event]=j:delete x[l.event];const p=await window.api.config.writeJson(m,{...d,hooks:x});if(a(null),!p.ok){f(p.error??"write failed");return}h()};return t?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx(L,{query:u,onQueryChange:y,count:v.length,total:_.length}),(c||i)&&e.jsx("div",{className:`px-4 py-2 text-xs border-b border-line ${i?"text-red-400 bg-red-950/20":"text-accent bg-bg-elev"}`,children:i??c}),e.jsxs("div",{className:"flex-1 overflow-auto divide-y divide-line",children:[v.map(l=>{const w=ne(n,l);return e.jsxs("div",{className:"px-4 py-3 flex items-start gap-3 hover:bg-bg-elev/50",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-fg text-xs font-medium",children:l.name}),e.jsx(C,{tone:"dim",children:l.event}),l.matcher&&e.jsxs(C,{tone:"dim",children:["match: ",l.matcher]}),w&&e.jsx(C,{tone:"accent",children:"installed"})]}),e.jsx("div",{className:"text-fg-dim text-xs mt-0.5",children:l.description}),e.jsx("div",{className:"text-fg-faint text-[10px] font-mono mt-1 truncate",children:l.command})]}),e.jsx("div",{className:"flex gap-1 shrink-0",children:w?e.jsx("button",{disabled:s===l.id,onClick:()=>b(l),className:"px-2 py-0.5 text-xs border border-line rounded text-fg-dim hover:text-red-400",children:"remove"}):e.jsx("button",{disabled:s===l.id,onClick:()=>S(l),className:"px-2 py-0.5 text-xs border border-accent rounded text-accent hover:bg-accent hover:text-bg",children:s===l.id?"…":"install"})})]},l.id)}),v.length===0&&e.jsx(N,{title:"no matches"})]})]}):e.jsx(N,{title:"loading…"})}function ge(){const t=D(),[n,r]=g.useState(""),[s,a]=g.useState(null),[c,o]=g.useState(null),[i,f]=g.useState(null),[u,y]=g.useState(""),m=t?`${t}/.claude/settings.json`:null,h=async()=>{if(!m)return;const b=await window.api.config.readJson(m),l=(b.data&&typeof b.data=="object"?b.data:{})??{};r(JSON.stringify(l.permissions??{}))};g.useEffect(()=>{h()},[m]);const v=g.useMemo(()=>z.filter(b=>I(u,b.id,b.name,b.description)),[u]),S=async b=>{if(!m)return;a(b.id),f(null);const l=await window.api.config.readJson(m),w=(l.data&&typeof l.data=="object"?l.data:{})??{},d=await window.api.config.writeJson(m,{...w,permissions:b.permissions});if(a(null),!d.ok){f(d.error??"write failed");return}o(`applied ${b.id} — replaces existing permissions block`),setTimeout(()=>o(null),3e3),h()};return t?e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx(L,{query:u,onQueryChange:y,count:v.length,total:z.length}),(c||i)&&e.jsx("div",{className:`px-4 py-2 text-xs border-b border-line ${i?"text-red-400 bg-red-950/20":"text-accent bg-bg-elev"}`,children:i??c}),e.jsxs("div",{className:"flex-1 overflow-auto divide-y divide-line",children:[v.map(b=>{const l=n===JSON.stringify(b.permissions),w=[];return b.permissions.allow&&w.push(`${b.permissions.allow.length} allow`),b.permissions.deny&&w.push(`${b.permissions.deny.length} deny`),b.permissions.ask&&w.push(`${b.permissions.ask.length} ask`),b.permissions.defaultMode&&w.push(`mode: ${b.permissions.defaultMode}`),e.jsxs("div",{className:"px-4 py-3 flex items-start gap-3 hover:bg-bg-elev/50",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-fg text-xs font-medium",children:b.name}),l&&e.jsx(C,{tone:"accent",children:"active"}),e.jsx(C,{tone:"warn",children:"replaces permissions"})]}),e.jsx("div",{className:"text-fg-dim text-xs mt-0.5",children:b.description}),e.jsx("div",{className:"text-fg-faint text-[10px] font-mono mt-1 truncate",children:w.join(" · ")})]}),e.jsx("div",{className:"flex gap-1 shrink-0",children:e.jsx("button",{disabled:s===b.id,onClick:()=>S(b),className:"px-2 py-0.5 text-xs border border-accent rounded text-accent hover:bg-accent hover:text-bg",children:s===b.id?"…":"apply"})})]},b.id)}),v.length===0&&e.jsx(N,{title:"no matches"})]})]}):e.jsx(N,{title:"loading…"})}const ae={communication:"Communication","working-style":"Working style",security:"Security",testing:"Testing",review:"Code review",documentation:"Documentation",debugging:"Debugging",architecture:"Architecture",refactoring:"Refactoring",performance:"Performance",collaboration:"Collaboration",domain:"Domain / stack"};function he(){const t=D(),[n,r]=g.useState(""),[s,a]=g.useState(null),[c,o]=g.useState(null),[i,f]=g.useState(null),[u,y]=g.useState(""),m=t?`${t}/.claude/CLAUDE.md`:null,h=async()=>{if(!m)return;const p=await window.api.config.readText(m);r(p.text)};g.useEffect(()=>{h()},[m]);const v=g.useMemo(()=>new Set(W(n)),[n]),S=g.useMemo(()=>te(n,R),[n]),b=async()=>{if(!m||S.length===0)return;f(null);const p=ie(n,S),k=await window.api.config.writeText(m,p);if(!k.ok){f(k.error??"write failed");return}o(`removed ${S.length} unmanaged section(s)`),setTimeout(()=>o(null),3e3),h()},l=g.useMemo(()=>R.filter(p=>I(u,p.id,p.name,p.description,p.section,...p.tags??[])),[u]),w=g.useMemo(()=>{const p=new Map;for(const k of l){const A=p.get(k.category)??[];A.push(k),p.set(k.category,A)}return p},[l]),d=async p=>{if(!m)return;a(p.id),f(null);const k=ee(n,p.id,R),A=await window.api.config.writeText(m,k);if(a(null),!A.ok){f(A.error??"write failed");return}const B=!v.has(p.id);o(B?`enabled "${p.name}"`:`disabled "${p.name}"`),setTimeout(()=>o(null),2500),h()};if(!t)return e.jsx(N,{title:"loading…"});const x=v.size,j=["communication","working-style","testing","review","security","debugging","architecture","refactoring","performance","documentation","collaboration","domain"];return e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{className:"shrink-0 border-b border-line bg-bg-elev px-3 py-1.5 flex items-center gap-2 text-xs",children:[e.jsx("span",{className:"text-fg-faint",children:x>0?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-fg-dim font-medium",children:x})," active · managed in"," ",e.jsx("code",{className:"text-fg-faint",children:"~/.claude/CLAUDE.md"})]}):e.jsx(e.Fragment,{children:"nothing active — toggle presets below to stack them in your CLAUDE.md"})}),e.jsx("div",{className:"flex-1"}),e.jsx("span",{className:"text-fg-faint",children:l.length===R.length?`${R.length} available`:`${l.length} of ${R.length}`}),e.jsx("input",{value:u,onChange:p=>y(p.target.value),placeholder:"search presets…",className:"bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg w-56"})]}),(c||i)&&e.jsx("div",{className:`px-4 py-2 text-xs border-b border-line ${i?"text-red-400 bg-red-950/20":"text-accent bg-bg-elev"}`,children:i??c}),S.length>0&&e.jsxs("div",{className:"px-4 py-2 text-xs border-b border-line bg-yellow-950/20 flex items-start gap-3",children:[e.jsxs("div",{className:"flex-1 text-yellow-500/90",children:[e.jsx("div",{className:"font-medium",children:"Your CLAUDE.md has unmanaged sections that will collide with presets:"}),e.jsx("div",{className:"text-yellow-500/70 mt-0.5",children:S.map(p=>`# ${p}`).join(" · ")}),e.jsx("div",{className:"text-fg-faint mt-1",children:"These were probably added before presets were toggleable. Clean them out so the managed block owns those sections."})]}),e.jsxs("button",{onClick:b,className:"shrink-0 px-3 py-1 text-xs border border-yellow-600/60 rounded text-yellow-400 hover:bg-yellow-600 hover:text-bg",children:["remove ",S.length," section",S.length>1?"s":""]})]}),e.jsxs("div",{className:"flex-1 overflow-auto",children:[j.map(p=>({cat:p,presets:w.get(p)??[]})).filter(p=>p.presets.length>0).map(({cat:p,presets:k})=>e.jsx(oe,{title:ae[p],presets:k,activeIds:v,existing:n,busy:s,onToggle:d},p)),l.length===0&&e.jsx(N,{title:"no matches"})]})]})}function oe({title:t,presets:n,activeIds:r,existing:s,busy:a,onToggle:c}){const[o,i]=g.useState(!0),f=n.filter(u=>r.has(u.id)).length;return e.jsxs("section",{className:"border-b border-line",children:[e.jsxs("header",{className:"px-4 py-2 bg-bg-elev/40 cursor-pointer hover:bg-bg-elev flex items-center gap-3",onClick:()=>i(!o),children:[e.jsx("span",{className:"text-fg-faint w-3",children:o?"▾":"▸"}),e.jsx("h2",{className:"text-fg text-sm font-medium flex-1",children:t}),e.jsx("span",{className:"text-fg-faint text-xs",children:f>0?`${f}/${n.length} active`:`${n.length}`})]}),o&&e.jsx("div",{className:"divide-y divide-line/60",children:n.map(u=>{const y=r.has(u.id),m=se(s,u,R);return e.jsxs("div",{className:"px-4 py-3 flex items-start gap-3 hover:bg-bg-elev/20",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"text-fg text-sm",children:u.name}),y&&e.jsx(C,{tone:"accent",children:"active"}),e.jsxs("span",{className:"text-[10px] px-1 py-0 rounded border border-line bg-bg-elev text-fg-faint uppercase tracking-wide",children:["→ # ",u.section]}),!y&&m>0&&e.jsxs("span",{className:"text-[10px] px-1 py-0 rounded border border-yellow-900/40 bg-yellow-950/30 text-yellow-500/80 uppercase tracking-wide",children:["merges with ",m]})]}),e.jsx("div",{className:"text-fg-dim text-xs mt-0.5",children:u.description}),e.jsxs("ul",{className:"text-fg-faint text-[11px] mt-1 space-y-0.5 list-disc list-inside",children:[u.bullets.slice(0,2).map((h,v)=>e.jsx("li",{className:"truncate",children:h},v)),u.bullets.length>2&&e.jsxs("li",{className:"text-fg-faint italic",children:["+",u.bullets.length-2," more"]})]})]}),e.jsx("div",{className:"flex gap-1 shrink-0",children:e.jsx("button",{disabled:a===u.id,onClick:()=>c(u),className:`px-3 py-0.5 text-xs rounded border transition-colors ${y?"bg-accent text-bg border-accent hover:bg-transparent hover:text-fg-dim":"bg-bg-elev text-fg-dim border-line hover:text-fg hover:bg-bg-hi"}`,title:y?"remove from CLAUDE.md":"add to CLAUDE.md",children:a===u.id?"…":y?"on":"off"})})]},u.id)})})]})}function fe({active:t,onChange:n,installedLabel:r="Installed",libraryLabel:s="Library"}){return e.jsx("div",{className:"flex rounded border border-line overflow-hidden",children:[["installed",r],["library",s]].map(([a,c])=>e.jsx("button",{onClick:()=>n(a),className:`px-2 py-0.5 text-xs ${t===a?"bg-bg-hi text-fg":"text-fg-dim hover:text-fg hover:bg-bg-hi"}`,children:c},a))})}function L({query:t,onQueryChange:n,count:r,total:s}){return e.jsxs("div",{className:"shrink-0 border-b border-line bg-bg-elev px-3 py-1.5 flex items-center gap-2 text-xs",children:[e.jsx("span",{className:"text-fg-faint",children:r===s?`${s} available`:`${r} of ${s}`}),e.jsx("div",{className:"flex-1"}),e.jsx("input",{value:t,onChange:a=>n(a.target.value),placeholder:"filter…",className:"bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg w-48"})]})}function G({href:t,children:n}){return e.jsx("a",{href:t,target:"_blank",rel:"noreferrer",className:"px-2 py-0.5 text-xs border border-line rounded text-fg-dim hover:text-fg hover:bg-bg-hi",children:n})}function re({id:t,marketplace:n,installed:r,onDone:s}){const[a,c]=g.useState("idle"),[o,i]=g.useState([]),[f,u]=g.useState(!1),y=g.useRef(!0);g.useEffect(()=>()=>{y.current=!1},[]),g.useEffect(()=>{const h=window.api.plugins.onInstallProgress(({slug:v,line:S})=>{v===t&&i(b=>{const l=[...b,S];return l.length>200?l.slice(l.length-200):l})});return()=>h()},[t]);const m=async()=>{c("running"),i([]),u(!0);try{const h=await window.api.plugins.install({slug:t,marketplace:n});if(!y.current){h.ok?(T.info(`Installed ${t}`),s()):T.error(`Install failed: ${t} (exit ${h.exitCode})${h.error?` — ${h.error}`:""}`);return}h.ok?(c("idle"),T.info(`Installed ${t}`),s()):(c("error"),T.error(`Install failed: ${t} (exit ${h.exitCode})${h.error?` — ${h.error}`:""}`))}catch(h){if(!y.current){T.error(`Install error: ${t} — ${h instanceof Error?h.message:String(h)}`);return}c("error"),T.error(`Install error: ${t} — ${h instanceof Error?h.message:String(h)}`)}};return r?e.jsx("button",{disabled:!0,className:"px-2 py-0.5 text-xs border border-line rounded text-fg-faint bg-bg-elev cursor-default",children:"installed"}):e.jsxs("div",{className:"flex flex-col items-end gap-1",children:[e.jsx("button",{onClick:m,disabled:a==="running",className:`px-2 py-0.5 text-xs border rounded ${a==="running"?"border-line text-fg-faint bg-bg-elev cursor-not-allowed":"border-accent/50 text-accent hover:bg-accent hover:text-bg"}`,children:a==="running"?"installing…":a==="error"?"retry":"install"}),o.length>0&&e.jsx("button",{onClick:()=>u(h=>!h),className:"text-[10px] text-fg-faint hover:text-fg-dim",children:f?"hide log":"show log"}),f&&o.length>0&&e.jsx("pre",{className:"mt-0.5 max-h-40 w-72 overflow-auto bg-bg-elev border border-line rounded p-2 text-fg-faint font-mono text-[10px] whitespace-pre-wrap text-left",children:o.join(`
46
+ `)})]})}function V({text:t,label:n}){const[r,s]=g.useState(!1);return e.jsx("button",{onClick:()=>{navigator.clipboard.writeText(t),s(!0),setTimeout(()=>s(!1),1500)},className:"px-2 py-0.5 text-xs border border-accent/50 rounded text-accent hover:bg-accent hover:text-bg",children:r?"copied!":n})}export{le as C,pe as H,de as M,ge as P,ue as S,fe as V,_ as a,q as b,F as c,M as d,me as e,he as f,J as g};