@macpaw/cctk 1.0.0-beta.1
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.
- package/License +21 -0
- package/README.md +142 -0
- package/bin/index.js +5 -0
- package/dist/index.js +1 -0
- package/package.json +65 -0
- package/templates/claude/agents/brainstormer.md +113 -0
- package/templates/claude/agents/code-reviewer.md +157 -0
- package/templates/claude/agents/copywriter.md +110 -0
- package/templates/claude/agents/database-admin.md +92 -0
- package/templates/claude/agents/debugger.md +137 -0
- package/templates/claude/agents/docs-manager.md +208 -0
- package/templates/claude/agents/fullstack-developer.md +95 -0
- package/templates/claude/agents/git-manager.md +394 -0
- package/templates/claude/agents/journal-writer.md +113 -0
- package/templates/claude/agents/mcp-manager.md +89 -0
- package/templates/claude/agents/planner.md +108 -0
- package/templates/claude/agents/project-manager.md +125 -0
- package/templates/claude/agents/registry.json +304 -0
- package/templates/claude/agents/researcher.md +37 -0
- package/templates/claude/agents/scout-external.md +140 -0
- package/templates/claude/agents/scout.md +106 -0
- package/templates/claude/agents/tester.md +105 -0
- package/templates/claude/agents/ui-ux-designer.md +208 -0
- package/templates/claude/commands/ask.md +56 -0
- package/templates/claude/commands/bootstrap/auto/fast.md +106 -0
- package/templates/claude/commands/bootstrap/auto/parallel.md +64 -0
- package/templates/claude/commands/bootstrap/auto.md +110 -0
- package/templates/claude/commands/bootstrap.md +130 -0
- package/templates/claude/commands/brainstorm.md +75 -0
- package/templates/claude/commands/code/auto.md +198 -0
- package/templates/claude/commands/code/no-test.md +172 -0
- package/templates/claude/commands/code/parallel.md +100 -0
- package/templates/claude/commands/code.md +197 -0
- package/templates/claude/commands/coding-level.md +37 -0
- package/templates/claude/commands/content/cro.md +41 -0
- package/templates/claude/commands/content/enhance.md +12 -0
- package/templates/claude/commands/content/fast.md +11 -0
- package/templates/claude/commands/content/good.md +14 -0
- package/templates/claude/commands/cook/auto/fast.md +26 -0
- package/templates/claude/commands/cook/auto/parallel.md +49 -0
- package/templates/claude/commands/cook/auto.md +15 -0
- package/templates/claude/commands/cook.md +101 -0
- package/templates/claude/commands/debug.md +13 -0
- package/templates/claude/commands/docs/init.md +37 -0
- package/templates/claude/commands/docs/summarize.md +22 -0
- package/templates/claude/commands/docs/update.md +78 -0
- package/templates/claude/commands/fix/ci.md +17 -0
- package/templates/claude/commands/fix/fast.md +18 -0
- package/templates/claude/commands/fix/hard.md +35 -0
- package/templates/claude/commands/fix/logs.md +26 -0
- package/templates/claude/commands/fix/parallel.md +54 -0
- package/templates/claude/commands/fix/test.md +20 -0
- package/templates/claude/commands/fix/types.md +9 -0
- package/templates/claude/commands/fix/ui.md +33 -0
- package/templates/claude/commands/fix.md +43 -0
- package/templates/claude/commands/git/cm.md +5 -0
- package/templates/claude/commands/git/cp.md +4 -0
- package/templates/claude/commands/git/merge.md +40 -0
- package/templates/claude/commands/git/pr.md +50 -0
- package/templates/claude/commands/journal.md +7 -0
- package/templates/claude/commands/kanban.md +99 -0
- package/templates/claude/commands/plan/archive.md +57 -0
- package/templates/claude/commands/plan/ci.md +33 -0
- package/templates/claude/commands/plan/cro.md +67 -0
- package/templates/claude/commands/plan/fast.md +66 -0
- package/templates/claude/commands/plan/hard.md +92 -0
- package/templates/claude/commands/plan/parallel.md +129 -0
- package/templates/claude/commands/plan/two.md +45 -0
- package/templates/claude/commands/plan/validate.md +117 -0
- package/templates/claude/commands/plan.md +30 -0
- package/templates/claude/commands/preview.md +87 -0
- package/templates/claude/commands/registry.json +313 -0
- package/templates/claude/commands/review/codebase/parallel.md +122 -0
- package/templates/claude/commands/review/codebase.md +47 -0
- package/templates/claude/commands/scout/ext.md +35 -0
- package/templates/claude/commands/scout.md +28 -0
- package/templates/claude/commands/skill/add.md +36 -0
- package/templates/claude/commands/skill/create.md +29 -0
- package/templates/claude/commands/skill/fix-logs.md +22 -0
- package/templates/claude/commands/skill/optimize/auto.md +25 -0
- package/templates/claude/commands/skill/optimize.md +34 -0
- package/templates/claude/commands/skill/plan.md +45 -0
- package/templates/claude/commands/test/ui.md +91 -0
- package/templates/claude/commands/test.md +8 -0
- package/templates/claude/commands/use-mcp.md +34 -0
- package/templates/claude/commands/watzup.md +8 -0
- package/templates/claude/commands/worktree.md +126 -0
- package/templates/claude/hooks/dev-rules-reminder.cjs +258 -0
- package/templates/claude/hooks/docs/README.md +42 -0
- package/templates/claude/hooks/lib/cctk-config-utils.cjs +751 -0
- package/templates/claude/hooks/lib/cctk-paths.cjs +106 -0
- package/templates/claude/hooks/lib/context-tracker.cjs +346 -0
- package/templates/claude/hooks/privacy-block.cjs +289 -0
- package/templates/claude/hooks/registry.json +77 -0
- package/templates/claude/hooks/scout-block/broad-pattern-detector.cjs +293 -0
- package/templates/claude/hooks/scout-block/error-formatter.cjs +156 -0
- package/templates/claude/hooks/scout-block/path-extractor.cjs +359 -0
- package/templates/claude/hooks/scout-block/pattern-matcher.cjs +184 -0
- package/templates/claude/hooks/scout-block/vendor/ignore.js +626 -0
- package/templates/claude/hooks/scout-block.cjs +167 -0
- package/templates/claude/hooks/session-end.cjs +35 -0
- package/templates/claude/hooks/session-init.cjs +214 -0
- package/templates/claude/hooks/subagent-init.cjs +161 -0
- package/templates/claude/hooks/write-compact-marker.cjs +153 -0
- package/templates/claude/output-styles/coding-level-1.md +148 -0
- package/templates/claude/output-styles/coding-level-2.md +159 -0
- package/templates/claude/output-styles/coding-level-3.md +91 -0
- package/templates/claude/scripts/README.md +33 -0
- package/templates/claude/scripts/generate-catalogs.cjs +318 -0
- package/templates/claude/scripts/registry.json +48 -0
- package/templates/claude/scripts/set-active-plan.cjs +45 -0
- package/templates/claude/scripts/validate-docs.cjs +447 -0
- package/templates/claude/scripts/worktree.cjs +658 -0
- package/templates/claude/skills/README.md +112 -0
- package/templates/claude/skills/ai-artist/SKILL.md +75 -0
- package/templates/claude/skills/ai-artist/references/advanced-techniques.md +184 -0
- package/templates/claude/skills/ai-artist/references/domain-code.md +66 -0
- package/templates/claude/skills/ai-artist/references/domain-data.md +72 -0
- package/templates/claude/skills/ai-artist/references/domain-marketing.md +66 -0
- package/templates/claude/skills/ai-artist/references/domain-patterns.md +33 -0
- package/templates/claude/skills/ai-artist/references/domain-writing.md +68 -0
- package/templates/claude/skills/ai-artist/references/image-prompting.md +141 -0
- package/templates/claude/skills/ai-artist/references/llm-prompting.md +165 -0
- package/templates/claude/skills/ai-artist/references/nano-banana.md +59 -0
- package/templates/claude/skills/ai-artist/references/reasoning-techniques.md +201 -0
- package/templates/claude/skills/backend-development/SKILL.md +95 -0
- package/templates/claude/skills/backend-development/references/backend-api-design.md +495 -0
- package/templates/claude/skills/backend-development/references/backend-architecture.md +454 -0
- package/templates/claude/skills/backend-development/references/backend-authentication.md +338 -0
- package/templates/claude/skills/backend-development/references/backend-code-quality.md +659 -0
- package/templates/claude/skills/backend-development/references/backend-debugging.md +904 -0
- package/templates/claude/skills/backend-development/references/backend-devops.md +494 -0
- package/templates/claude/skills/backend-development/references/backend-mindset.md +387 -0
- package/templates/claude/skills/backend-development/references/backend-performance.md +397 -0
- package/templates/claude/skills/backend-development/references/backend-security.md +290 -0
- package/templates/claude/skills/backend-development/references/backend-technologies.md +256 -0
- package/templates/claude/skills/backend-development/references/backend-testing.md +429 -0
- package/templates/claude/skills/better-auth/SKILL.md +204 -0
- package/templates/claude/skills/better-auth/references/advanced-features.md +553 -0
- package/templates/claude/skills/better-auth/references/database-integration.md +577 -0
- package/templates/claude/skills/better-auth/references/email-password-auth.md +416 -0
- package/templates/claude/skills/better-auth/references/oauth-providers.md +430 -0
- package/templates/claude/skills/better-auth/scripts/better_auth_init.py +521 -0
- package/templates/claude/skills/chrome-devtools/SKILL.md +473 -0
- package/templates/claude/skills/chrome-devtools/references/cdp-domains.md +694 -0
- package/templates/claude/skills/chrome-devtools/references/performance-guide.md +940 -0
- package/templates/claude/skills/chrome-devtools/references/puppeteer-reference.md +953 -0
- package/templates/claude/skills/chrome-devtools/scripts/README.md +288 -0
- package/templates/claude/skills/chrome-devtools/scripts/aria-snapshot.js +368 -0
- package/templates/claude/skills/chrome-devtools/scripts/click.js +92 -0
- package/templates/claude/skills/chrome-devtools/scripts/console.js +85 -0
- package/templates/claude/skills/chrome-devtools/scripts/evaluate.js +59 -0
- package/templates/claude/skills/chrome-devtools/scripts/fill.js +84 -0
- package/templates/claude/skills/chrome-devtools/scripts/inject-auth.js +247 -0
- package/templates/claude/skills/chrome-devtools/scripts/install-deps.sh +11 -0
- package/templates/claude/skills/chrome-devtools/scripts/install.sh +36 -0
- package/templates/claude/skills/chrome-devtools/scripts/lib/browser.js +335 -0
- package/templates/claude/skills/chrome-devtools/scripts/lib/selector.js +183 -0
- package/templates/claude/skills/chrome-devtools/scripts/navigate.js +60 -0
- package/templates/claude/skills/chrome-devtools/scripts/network.js +113 -0
- package/templates/claude/skills/chrome-devtools/scripts/package.json +16 -0
- package/templates/claude/skills/chrome-devtools/scripts/performance.js +159 -0
- package/templates/claude/skills/chrome-devtools/scripts/screenshot.js +212 -0
- package/templates/claude/skills/chrome-devtools/scripts/select-ref.js +151 -0
- package/templates/claude/skills/chrome-devtools/scripts/snapshot.js +143 -0
- package/templates/claude/skills/chrome-devtools/scripts/ws-debug.js +47 -0
- package/templates/claude/skills/chrome-devtools/scripts/ws-full-debug.js +115 -0
- package/templates/claude/skills/claude-code/references/advanced-features.md +399 -0
- package/templates/claude/skills/claude-code/references/agent-skills.md +399 -0
- package/templates/claude/skills/claude-code/references/api-reference.md +498 -0
- package/templates/claude/skills/claude-code/references/best-practices.md +447 -0
- package/templates/claude/skills/claude-code/references/cicd-integration.md +428 -0
- package/templates/claude/skills/claude-code/references/common-workflows.md +107 -0
- package/templates/claude/skills/claude-code/references/configuration.md +480 -0
- package/templates/claude/skills/claude-code/references/enterprise-features.md +472 -0
- package/templates/claude/skills/claude-code/references/getting-started.md +244 -0
- package/templates/claude/skills/claude-code/references/hooks-and-plugins.md +444 -0
- package/templates/claude/skills/claude-code/references/hooks-comprehensive.md +622 -0
- package/templates/claude/skills/claude-code/references/ide-integration.md +316 -0
- package/templates/claude/skills/claude-code/references/mcp-integration.md +386 -0
- package/templates/claude/skills/claude-code/references/slash-commands.md +460 -0
- package/templates/claude/skills/claude-code/references/troubleshooting.md +455 -0
- package/templates/claude/skills/claude-code/skill.md +60 -0
- package/templates/claude/skills/code-review/SKILL.md +143 -0
- package/templates/claude/skills/code-review/references/code-review-reception.md +209 -0
- package/templates/claude/skills/code-review/references/requesting-code-review.md +105 -0
- package/templates/claude/skills/code-review/references/verification-before-completion.md +139 -0
- package/templates/claude/skills/context-engineering/SKILL.md +86 -0
- package/templates/claude/skills/context-engineering/references/context-compression.md +84 -0
- package/templates/claude/skills/context-engineering/references/context-degradation.md +93 -0
- package/templates/claude/skills/context-engineering/references/context-fundamentals.md +75 -0
- package/templates/claude/skills/context-engineering/references/context-optimization.md +82 -0
- package/templates/claude/skills/context-engineering/references/evaluation.md +89 -0
- package/templates/claude/skills/context-engineering/references/memory-systems.md +88 -0
- package/templates/claude/skills/context-engineering/references/multi-agent-patterns.md +90 -0
- package/templates/claude/skills/context-engineering/references/project-development.md +97 -0
- package/templates/claude/skills/context-engineering/references/tool-design.md +86 -0
- package/templates/claude/skills/context-engineering/scripts/compression_evaluator.py +329 -0
- package/templates/claude/skills/context-engineering/scripts/context_analyzer.py +294 -0
- package/templates/claude/skills/databases/SKILL.md +232 -0
- package/templates/claude/skills/databases/references/mongodb-aggregation.md +447 -0
- package/templates/claude/skills/databases/references/mongodb-atlas.md +465 -0
- package/templates/claude/skills/databases/references/mongodb-crud.md +408 -0
- package/templates/claude/skills/databases/references/mongodb-indexing.md +442 -0
- package/templates/claude/skills/databases/references/postgresql-administration.md +594 -0
- package/templates/claude/skills/databases/references/postgresql-performance.md +527 -0
- package/templates/claude/skills/databases/references/postgresql-psql-cli.md +467 -0
- package/templates/claude/skills/databases/references/postgresql-queries.md +475 -0
- package/templates/claude/skills/databases/scripts/db_backup.py +502 -0
- package/templates/claude/skills/databases/scripts/db_migrate.py +414 -0
- package/templates/claude/skills/databases/scripts/db_performance_check.py +445 -0
- package/templates/claude/skills/debugging/SKILL.md +84 -0
- package/templates/claude/skills/debugging/references/defense-in-depth.md +124 -0
- package/templates/claude/skills/debugging/references/root-cause-tracing.md +122 -0
- package/templates/claude/skills/debugging/references/systematic-debugging.md +102 -0
- package/templates/claude/skills/debugging/references/verification.md +123 -0
- package/templates/claude/skills/debugging/scripts/find-polluter.sh +63 -0
- package/templates/claude/skills/debugging/scripts/find-polluter.test.md +102 -0
- package/templates/claude/skills/devops/SKILL.md +293 -0
- package/templates/claude/skills/devops/references/browser-rendering.md +305 -0
- package/templates/claude/skills/devops/references/cloudflare-d1-kv.md +123 -0
- package/templates/claude/skills/devops/references/cloudflare-platform.md +271 -0
- package/templates/claude/skills/devops/references/cloudflare-r2-storage.md +280 -0
- package/templates/claude/skills/devops/references/cloudflare-workers-advanced.md +312 -0
- package/templates/claude/skills/devops/references/cloudflare-workers-apis.md +309 -0
- package/templates/claude/skills/devops/references/cloudflare-workers-basics.md +418 -0
- package/templates/claude/skills/devops/references/docker-basics.md +297 -0
- package/templates/claude/skills/devops/references/docker-compose.md +292 -0
- package/templates/claude/skills/devops/references/gcloud-platform.md +307 -0
- package/templates/claude/skills/devops/references/gcloud-services.md +304 -0
- package/templates/claude/skills/devops/scripts/cloudflare_deploy.py +269 -0
- package/templates/claude/skills/devops/scripts/docker_optimize.py +320 -0
- package/templates/claude/skills/docs-seeker/SKILL.md +95 -0
- package/templates/claude/skills/docs-seeker/package.json +24 -0
- package/templates/claude/skills/docs-seeker/references/advanced.md +78 -0
- package/templates/claude/skills/docs-seeker/references/context7-patterns.md +68 -0
- package/templates/claude/skills/docs-seeker/references/errors.md +68 -0
- package/templates/claude/skills/docs-seeker/scripts/analyze-llms-txt.js +245 -0
- package/templates/claude/skills/docs-seeker/scripts/detect-topic.js +172 -0
- package/templates/claude/skills/docs-seeker/scripts/fetch-docs.js +212 -0
- package/templates/claude/skills/docs-seeker/workflows/library-search.md +87 -0
- package/templates/claude/skills/docs-seeker/workflows/repo-analysis.md +91 -0
- package/templates/claude/skills/docs-seeker/workflows/topic-search.md +77 -0
- package/templates/claude/skills/frontend-design/SKILL.md +85 -0
- package/templates/claude/skills/frontend-design/references/analysis-best-practices.md +80 -0
- package/templates/claude/skills/frontend-design/references/analysis-prompts.md +141 -0
- package/templates/claude/skills/frontend-design/references/analysis-techniques.md +118 -0
- package/templates/claude/skills/frontend-design/references/animejs.md +396 -0
- package/templates/claude/skills/frontend-design/references/design-extraction-overview.md +71 -0
- package/templates/claude/skills/frontend-design/references/extraction-best-practices.md +141 -0
- package/templates/claude/skills/frontend-design/references/extraction-output-templates.md +162 -0
- package/templates/claude/skills/frontend-design/references/extraction-prompts.md +127 -0
- package/templates/claude/skills/frontend-design/references/technical-accessibility.md +119 -0
- package/templates/claude/skills/frontend-design/references/technical-best-practices.md +97 -0
- package/templates/claude/skills/frontend-design/references/technical-optimization.md +44 -0
- package/templates/claude/skills/frontend-design/references/technical-overview.md +90 -0
- package/templates/claude/skills/frontend-design/references/technical-workflows.md +150 -0
- package/templates/claude/skills/frontend-design/references/visual-analysis-overview.md +95 -0
- package/templates/claude/skills/frontend-development/SKILL.md +399 -0
- package/templates/claude/skills/frontend-development/resources/common-patterns.md +331 -0
- package/templates/claude/skills/frontend-development/resources/complete-examples.md +872 -0
- package/templates/claude/skills/frontend-development/resources/component-patterns.md +502 -0
- package/templates/claude/skills/frontend-development/resources/data-fetching.md +767 -0
- package/templates/claude/skills/frontend-development/resources/file-organization.md +502 -0
- package/templates/claude/skills/frontend-development/resources/loading-and-error-states.md +501 -0
- package/templates/claude/skills/frontend-development/resources/performance.md +406 -0
- package/templates/claude/skills/frontend-development/resources/routing-guide.md +364 -0
- package/templates/claude/skills/frontend-development/resources/styling-guide.md +428 -0
- package/templates/claude/skills/frontend-development/resources/typescript-standards.md +418 -0
- package/templates/claude/skills/markdown-novel-viewer/SKILL.md +272 -0
- package/templates/claude/skills/markdown-novel-viewer/assets/directory-browser.css +215 -0
- package/templates/claude/skills/markdown-novel-viewer/assets/favicon.png +0 -0
- package/templates/claude/skills/markdown-novel-viewer/assets/novel-theme.css +872 -0
- package/templates/claude/skills/markdown-novel-viewer/assets/reader.js +378 -0
- package/templates/claude/skills/markdown-novel-viewer/assets/template.html +85 -0
- package/templates/claude/skills/markdown-novel-viewer/package.json +15 -0
- package/templates/claude/skills/markdown-novel-viewer/scripts/lib/http-server.cjs +434 -0
- package/templates/claude/skills/markdown-novel-viewer/scripts/lib/markdown-renderer.cjs +335 -0
- package/templates/claude/skills/markdown-novel-viewer/scripts/lib/plan-navigator.cjs +509 -0
- package/templates/claude/skills/markdown-novel-viewer/scripts/lib/port-finder.cjs +49 -0
- package/templates/claude/skills/markdown-novel-viewer/scripts/lib/process-mgr.cjs +150 -0
- package/templates/claude/skills/markdown-novel-viewer/scripts/server.cjs +398 -0
- package/templates/claude/skills/mcp-builder/SKILL.md +328 -0
- package/templates/claude/skills/mcp-builder/reference/evaluation.md +602 -0
- package/templates/claude/skills/mcp-builder/reference/mcp_best_practices.md +915 -0
- package/templates/claude/skills/mcp-builder/reference/node_mcp_server.md +916 -0
- package/templates/claude/skills/mcp-builder/reference/python_mcp_server.md +752 -0
- package/templates/claude/skills/mcp-builder/scripts/connections.py +151 -0
- package/templates/claude/skills/mcp-builder/scripts/evaluation.py +381 -0
- package/templates/claude/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/templates/claude/skills/mcp-builder/scripts/requirements.txt +2 -0
- package/templates/claude/skills/mcp-management/README.md +219 -0
- package/templates/claude/skills/mcp-management/SKILL.md +209 -0
- package/templates/claude/skills/mcp-management/assets/tools.json +3146 -0
- package/templates/claude/skills/mcp-management/references/configuration.md +114 -0
- package/templates/claude/skills/mcp-management/references/gemini-cli-integration.md +209 -0
- package/templates/claude/skills/mcp-management/references/mcp-protocol.md +116 -0
- package/templates/claude/skills/mcp-management/scripts/.env.example +10 -0
- package/templates/claude/skills/mcp-management/scripts/cli.ts +202 -0
- package/templates/claude/skills/mcp-management/scripts/mcp-client.ts +247 -0
- package/templates/claude/skills/mcp-management/scripts/package.json +20 -0
- package/templates/claude/skills/mcp-management/scripts/tsconfig.json +15 -0
- package/templates/claude/skills/media-processing/SKILL.md +91 -0
- package/templates/claude/skills/media-processing/references/common-workflows.md +132 -0
- package/templates/claude/skills/media-processing/references/ffmpeg-encoding.md +358 -0
- package/templates/claude/skills/media-processing/references/ffmpeg-filters.md +503 -0
- package/templates/claude/skills/media-processing/references/ffmpeg-streaming.md +395 -0
- package/templates/claude/skills/media-processing/references/format-compatibility.md +375 -0
- package/templates/claude/skills/media-processing/references/imagemagick-batch.md +612 -0
- package/templates/claude/skills/media-processing/references/imagemagick-editing.md +623 -0
- package/templates/claude/skills/media-processing/references/rmbg-background-removal.md +66 -0
- package/templates/claude/skills/media-processing/references/troubleshooting.md +109 -0
- package/templates/claude/skills/media-processing/scripts/README.md +102 -0
- package/templates/claude/skills/media-processing/scripts/batch-remove-background.sh +124 -0
- package/templates/claude/skills/media-processing/scripts/batch_resize.py +342 -0
- package/templates/claude/skills/media-processing/scripts/media_convert.py +311 -0
- package/templates/claude/skills/media-processing/scripts/remove-background.sh +96 -0
- package/templates/claude/skills/media-processing/scripts/remove-bg-node.js +181 -0
- package/templates/claude/skills/mermaidjs-v11/SKILL.md +115 -0
- package/templates/claude/skills/mermaidjs-v11/references/cli-usage.md +228 -0
- package/templates/claude/skills/mermaidjs-v11/references/configuration.md +232 -0
- package/templates/claude/skills/mermaidjs-v11/references/diagram-types.md +315 -0
- package/templates/claude/skills/mermaidjs-v11/references/examples.md +344 -0
- package/templates/claude/skills/mermaidjs-v11/references/integration.md +310 -0
- package/templates/claude/skills/planning/SKILL.md +115 -0
- package/templates/claude/skills/planning/references/codebase-understanding.md +62 -0
- package/templates/claude/skills/planning/references/output-standards.md +127 -0
- package/templates/claude/skills/planning/references/plan-organization.md +150 -0
- package/templates/claude/skills/planning/references/research-phase.md +49 -0
- package/templates/claude/skills/planning/references/solution-design.md +63 -0
- package/templates/claude/skills/plans-kanban/SKILL.md +157 -0
- package/templates/claude/skills/plans-kanban/assets/dashboard-template.html +119 -0
- package/templates/claude/skills/plans-kanban/assets/dashboard.css +1594 -0
- package/templates/claude/skills/plans-kanban/assets/dashboard.js +659 -0
- package/templates/claude/skills/plans-kanban/assets/favicon.png +0 -0
- package/templates/claude/skills/plans-kanban/package.json +13 -0
- package/templates/claude/skills/plans-kanban/scripts/lib/dashboard-renderer.cjs +941 -0
- package/templates/claude/skills/plans-kanban/scripts/lib/http-server.cjs +310 -0
- package/templates/claude/skills/plans-kanban/scripts/lib/plan-metadata-extractor.cjs +489 -0
- package/templates/claude/skills/plans-kanban/scripts/lib/plan-parser.cjs +194 -0
- package/templates/claude/skills/plans-kanban/scripts/lib/plan-scanner.cjs +277 -0
- package/templates/claude/skills/plans-kanban/scripts/lib/port-finder.cjs +49 -0
- package/templates/claude/skills/plans-kanban/scripts/lib/process-mgr.cjs +128 -0
- package/templates/claude/skills/plans-kanban/scripts/server.cjs +249 -0
- package/templates/claude/skills/problem-solving/SKILL.md +96 -0
- package/templates/claude/skills/problem-solving/references/attribution.md +69 -0
- package/templates/claude/skills/problem-solving/references/collision-zone-thinking.md +79 -0
- package/templates/claude/skills/problem-solving/references/inversion-exercise.md +91 -0
- package/templates/claude/skills/problem-solving/references/meta-pattern-recognition.md +87 -0
- package/templates/claude/skills/problem-solving/references/scale-game.md +95 -0
- package/templates/claude/skills/problem-solving/references/simplification-cascades.md +80 -0
- package/templates/claude/skills/problem-solving/references/when-stuck.md +72 -0
- package/templates/claude/skills/registry.json +258 -0
- package/templates/claude/skills/repomix/SKILL.md +247 -0
- package/templates/claude/skills/repomix/references/configuration.md +211 -0
- package/templates/claude/skills/repomix/references/usage-patterns.md +232 -0
- package/templates/claude/skills/repomix/scripts/README.md +179 -0
- package/templates/claude/skills/repomix/scripts/repomix_batch.py +455 -0
- package/templates/claude/skills/repomix/scripts/repos.example.json +15 -0
- package/templates/claude/skills/research/SKILL.md +168 -0
- package/templates/claude/skills/sequential-thinking/.env.example +8 -0
- package/templates/claude/skills/sequential-thinking/README.md +183 -0
- package/templates/claude/skills/sequential-thinking/SKILL.md +94 -0
- package/templates/claude/skills/sequential-thinking/package.json +31 -0
- package/templates/claude/skills/sequential-thinking/references/advanced-strategies.md +79 -0
- package/templates/claude/skills/sequential-thinking/references/advanced-techniques.md +76 -0
- package/templates/claude/skills/sequential-thinking/references/core-patterns.md +95 -0
- package/templates/claude/skills/sequential-thinking/references/examples-api.md +88 -0
- package/templates/claude/skills/sequential-thinking/references/examples-architecture.md +94 -0
- package/templates/claude/skills/sequential-thinking/references/examples-debug.md +90 -0
- package/templates/claude/skills/sequential-thinking/scripts/format-thought.js +182 -0
- package/templates/claude/skills/sequential-thinking/scripts/process-thought.js +252 -0
- package/templates/claude/skills/skill-creator/LICENSE.txt +202 -0
- package/templates/claude/skills/skill-creator/SKILL.md +266 -0
- package/templates/claude/skills/skill-creator/references/agent-skills-spec.md +51 -0
- package/templates/claude/skills/skill-creator/scripts/encoding_utils.py +21 -0
- package/templates/claude/skills/skill-creator/scripts/init_skill.py +304 -0
- package/templates/claude/skills/skill-creator/scripts/package_skill.py +110 -0
- package/templates/claude/skills/skill-creator/scripts/quick_validate.py +66 -0
- package/templates/claude/skills/template-skill/SKILL.md +6 -0
- package/templates/claude/skills/vitest/SKILL.md +595 -0
- package/templates/claude/skills/vitest/references/async-patterns.md +82 -0
- package/templates/claude/skills/vitest/references/mock-patterns.md +78 -0
- package/templates/claude/skills/vitest/references/monorepo-setup.md +185 -0
- package/templates/claude/skills/vitest/references/turborepo-setup.md +332 -0
- package/templates/claude/skills/web-frameworks/SKILL.md +324 -0
- package/templates/claude/skills/web-frameworks/references/nextjs-app-router.md +465 -0
- package/templates/claude/skills/web-frameworks/references/nextjs-data-fetching.md +459 -0
- package/templates/claude/skills/web-frameworks/references/nextjs-optimization.md +511 -0
- package/templates/claude/skills/web-frameworks/references/nextjs-server-components.md +495 -0
- package/templates/claude/skills/web-frameworks/references/remix-icon-integration.md +603 -0
- package/templates/claude/skills/web-frameworks/references/turborepo-caching.md +551 -0
- package/templates/claude/skills/web-frameworks/references/turborepo-pipelines.md +517 -0
- package/templates/claude/skills/web-frameworks/references/turborepo-setup.md +542 -0
- package/templates/claude/skills/web-frameworks/scripts/nextjs_init.py +547 -0
- package/templates/claude/skills/web-frameworks/scripts/turborepo_migrate.py +394 -0
- package/templates/claude/workflows/development-rules.md +40 -0
- package/templates/claude/workflows/documentation-management.md +121 -0
- package/templates/claude/workflows/orchestration-protocol.md +16 -0
- package/templates/claude/workflows/primary-workflow.md +45 -0
- package/templates/claude/workflows/registry.json +37 -0
- package/templates/common/.cct.json +41 -0
- package/templates/common/.cctkignore +22 -0
- package/templates/common/.env.example +39 -0
- package/templates/common/.mcp.json.example +16 -0
- package/templates/common/metadata.json +15 -0
- package/templates/common/settings.json +79 -0
- package/templates/common/statusline.cjs +271 -0
- package/templates/config/.repomixignore +22 -0
- package/templates/config/AGENTS.md +55 -0
- package/templates/config/CLAUDE.md +87 -0
- package/templates/plans/bug-fix-template.md +69 -0
- package/templates/plans/feature-implementation-template.md +84 -0
- package/templates/plans/refactor-template.md +82 -0
- package/templates/plans/template-usage-guide.md +58 -0
|
@@ -0,0 +1,658 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Git Worktree Manager for Claude Code Toolkit
|
|
4
|
+
* Cross-platform Node.js script for creating isolated git worktrees
|
|
5
|
+
*
|
|
6
|
+
* Usage: node worktree.cjs <command> [options]
|
|
7
|
+
* Commands:
|
|
8
|
+
* create <project> <feature> Create a new worktree (project optional for standalone)
|
|
9
|
+
* remove <name-or-path> Remove a worktree and its branch
|
|
10
|
+
* info Get repo info (type, projects, env files)
|
|
11
|
+
* list List existing worktrees
|
|
12
|
+
*
|
|
13
|
+
* Options:
|
|
14
|
+
* --prefix <type> Branch prefix (feat|fix|refactor|docs|test|chore|perf)
|
|
15
|
+
* --json Output in JSON format for LLM consumption
|
|
16
|
+
* --env <files> Comma-separated list of .env files to copy
|
|
17
|
+
* --dry-run Show what would be done without executing
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const { execSync, spawnSync } = require('child_process');
|
|
21
|
+
const fs = require('fs');
|
|
22
|
+
const path = require('path');
|
|
23
|
+
|
|
24
|
+
// Constants
|
|
25
|
+
const MIN_NODE_VERSION = 18;
|
|
26
|
+
const MAX_BRANCH_NAME_LENGTH = 50;
|
|
27
|
+
const nodeVersion = parseInt(process.version.slice(1).split('.')[0], 10);
|
|
28
|
+
if (nodeVersion < MIN_NODE_VERSION) {
|
|
29
|
+
outputError('NODE_VERSION_ERROR', `Node.js ${MIN_NODE_VERSION}+ required. Current: ${process.version}`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Parse arguments
|
|
34
|
+
const args = process.argv.slice(2);
|
|
35
|
+
const jsonOutput = args.includes('--json');
|
|
36
|
+
const jsonIndex = args.indexOf('--json');
|
|
37
|
+
if (jsonIndex > -1) args.splice(jsonIndex, 1);
|
|
38
|
+
|
|
39
|
+
const prefixIndex = args.indexOf('--prefix');
|
|
40
|
+
let branchPrefix = 'feat';
|
|
41
|
+
if (prefixIndex > -1) {
|
|
42
|
+
branchPrefix = args[prefixIndex + 1] || 'feat';
|
|
43
|
+
args.splice(prefixIndex, 2);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const envIndex = args.indexOf('--env');
|
|
47
|
+
let envFilesToCopy = [];
|
|
48
|
+
if (envIndex > -1) {
|
|
49
|
+
envFilesToCopy = (args[envIndex + 1] || '').split(',').filter(Boolean);
|
|
50
|
+
args.splice(envIndex, 2);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const dryRunIndex = args.indexOf('--dry-run');
|
|
54
|
+
const dryRun = dryRunIndex > -1;
|
|
55
|
+
if (dryRunIndex > -1) args.splice(dryRunIndex, 1);
|
|
56
|
+
|
|
57
|
+
const command = args[0];
|
|
58
|
+
// For create: args[1] is project (or feature for standalone), args[2] is feature
|
|
59
|
+
// For remove: args[1] is worktree name or path
|
|
60
|
+
const arg1 = args[1];
|
|
61
|
+
const arg2 = args[2];
|
|
62
|
+
|
|
63
|
+
// Output helpers
|
|
64
|
+
function output(data) {
|
|
65
|
+
if (jsonOutput) {
|
|
66
|
+
console.log(JSON.stringify(data, null, 2));
|
|
67
|
+
} else {
|
|
68
|
+
if (data.success) {
|
|
69
|
+
console.log(`\n✅ ${data.message}`);
|
|
70
|
+
if (data.worktreePath) {
|
|
71
|
+
console.log(`\n📋 Next Steps:`);
|
|
72
|
+
console.log(` 1. cd ${data.worktreePath}`);
|
|
73
|
+
console.log(` 2. claude`);
|
|
74
|
+
console.log(` 3. Start working on your feature`);
|
|
75
|
+
console.log(`\n🧹 Cleanup when done:`);
|
|
76
|
+
console.log(` git worktree remove ${data.worktreePath}`);
|
|
77
|
+
console.log(` git branch -d ${data.branch}`);
|
|
78
|
+
}
|
|
79
|
+
if (data.envFilesCopied && data.envFilesCopied.length > 0) {
|
|
80
|
+
console.log(`\n📄 Environment files copied:`);
|
|
81
|
+
data.envFilesCopied.forEach(f => console.log(` ✓ ${f}`));
|
|
82
|
+
}
|
|
83
|
+
if (data.warnings && data.warnings.length > 0) {
|
|
84
|
+
console.log(`\n⚠️ Warnings:`);
|
|
85
|
+
data.warnings.forEach(w => console.log(` ${w}`));
|
|
86
|
+
}
|
|
87
|
+
} else if (data.info) {
|
|
88
|
+
// Info output
|
|
89
|
+
console.log(`\n📦 Repository Info:`);
|
|
90
|
+
console.log(` Type: ${data.repoType}`);
|
|
91
|
+
console.log(` Base branch: ${data.baseBranch}`);
|
|
92
|
+
if (data.projects && data.projects.length > 0) {
|
|
93
|
+
console.log(`\n📁 Available projects:`);
|
|
94
|
+
data.projects.forEach(p => console.log(` - ${p.name} (${p.path})`));
|
|
95
|
+
}
|
|
96
|
+
if (data.envFiles && data.envFiles.length > 0) {
|
|
97
|
+
console.log(`\n🔐 Environment files found:`);
|
|
98
|
+
data.envFiles.forEach(f => console.log(` - ${f}`));
|
|
99
|
+
}
|
|
100
|
+
if (data.dirtyState) {
|
|
101
|
+
console.log(`\n⚠️ Working directory has uncommitted changes`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function outputError(code, message, details = {}) {
|
|
108
|
+
const errorData = {
|
|
109
|
+
success: false,
|
|
110
|
+
error: { code, message, ...details }
|
|
111
|
+
};
|
|
112
|
+
if (jsonOutput) {
|
|
113
|
+
console.log(JSON.stringify(errorData, null, 2));
|
|
114
|
+
} else {
|
|
115
|
+
console.error(`\n❌ Error [${code}]: ${message}`);
|
|
116
|
+
if (details.suggestion) {
|
|
117
|
+
console.error(` 💡 ${details.suggestion}`);
|
|
118
|
+
}
|
|
119
|
+
if (details.availableProjects) {
|
|
120
|
+
console.error(`\n Available projects:`);
|
|
121
|
+
details.availableProjects.forEach(p => console.error(` - ${p}`));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Git command wrapper with error handling
|
|
128
|
+
function git(command, options = {}) {
|
|
129
|
+
try {
|
|
130
|
+
const result = execSync(`git ${command}`, {
|
|
131
|
+
encoding: 'utf-8',
|
|
132
|
+
stdio: options.silent ? 'pipe' : ['pipe', 'pipe', 'pipe'],
|
|
133
|
+
cwd: options.cwd || process.cwd()
|
|
134
|
+
});
|
|
135
|
+
return { success: true, output: result.trim() };
|
|
136
|
+
} catch (error) {
|
|
137
|
+
return {
|
|
138
|
+
success: false,
|
|
139
|
+
error: error.message,
|
|
140
|
+
stderr: error.stderr?.toString().trim() || '',
|
|
141
|
+
code: error.status
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Check if in git repo
|
|
147
|
+
function checkGitRepo() {
|
|
148
|
+
const result = git('rev-parse --show-toplevel', { silent: true });
|
|
149
|
+
if (!result.success) {
|
|
150
|
+
outputError('NOT_GIT_REPO', 'Not in a git repository', {
|
|
151
|
+
suggestion: 'Run this command from within a git repository'
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
return result.output;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Check git version supports worktree
|
|
158
|
+
function checkGitVersion() {
|
|
159
|
+
const result = git('worktree list', { silent: true });
|
|
160
|
+
if (!result.success && result.stderr.includes('not a git command')) {
|
|
161
|
+
outputError('GIT_VERSION_ERROR', 'Git version too old (worktree requires git 2.5+)', {
|
|
162
|
+
suggestion: 'Upgrade git to version 2.5 or newer'
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Detect base branch
|
|
168
|
+
function detectBaseBranch(cwd) {
|
|
169
|
+
const branches = ['dev', 'develop', 'main', 'master'];
|
|
170
|
+
for (const branch of branches) {
|
|
171
|
+
const local = git(`show-ref --verify --quiet refs/heads/${branch}`, { silent: true, cwd });
|
|
172
|
+
if (local.success) return branch;
|
|
173
|
+
const remote = git(`show-ref --verify --quiet refs/remotes/origin/${branch}`, { silent: true, cwd });
|
|
174
|
+
if (remote.success) return branch;
|
|
175
|
+
}
|
|
176
|
+
return 'main'; // fallback
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Check for uncommitted changes
|
|
180
|
+
function checkDirtyState() {
|
|
181
|
+
const diff = git('diff --quiet', { silent: true });
|
|
182
|
+
const diffCached = git('diff --cached --quiet', { silent: true });
|
|
183
|
+
return !diff.success || !diffCached.success;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Get dirty state details
|
|
187
|
+
function getDirtyStateDetails() {
|
|
188
|
+
const status = git('status --porcelain', { silent: true });
|
|
189
|
+
if (!status.success) return null;
|
|
190
|
+
const lines = status.output.split('\n').filter(Boolean);
|
|
191
|
+
const modified = lines.filter(l => l.startsWith(' M') || l.startsWith('M ')).length;
|
|
192
|
+
const staged = lines.filter(l => l.startsWith('A ') || l.startsWith('M ') || l.startsWith('D ')).length;
|
|
193
|
+
const untracked = lines.filter(l => l.startsWith('??')).length;
|
|
194
|
+
return { modified, staged, untracked, total: lines.length };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Parse .gitmodules for monorepo detection
|
|
198
|
+
function parseGitModules(gitRoot) {
|
|
199
|
+
const modulesPath = path.join(gitRoot, '.gitmodules');
|
|
200
|
+
if (!fs.existsSync(modulesPath)) return [];
|
|
201
|
+
|
|
202
|
+
const content = fs.readFileSync(modulesPath, 'utf-8');
|
|
203
|
+
const projects = [];
|
|
204
|
+
const pathRegex = /path\s*=\s*(.+)/g;
|
|
205
|
+
let match;
|
|
206
|
+
while ((match = pathRegex.exec(content)) !== null) {
|
|
207
|
+
const projectPath = match[1].trim();
|
|
208
|
+
projects.push({
|
|
209
|
+
path: projectPath,
|
|
210
|
+
name: path.basename(projectPath)
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
return projects;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Find .env files
|
|
217
|
+
function findEnvFiles(dir) {
|
|
218
|
+
try {
|
|
219
|
+
const files = fs.readdirSync(dir);
|
|
220
|
+
return files.filter(f => {
|
|
221
|
+
if (!f.startsWith('.env')) return false;
|
|
222
|
+
const fullPath = path.join(dir, f);
|
|
223
|
+
const stat = fs.statSync(fullPath);
|
|
224
|
+
return stat.isFile() && !stat.isSymbolicLink();
|
|
225
|
+
});
|
|
226
|
+
} catch {
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Find matching projects
|
|
232
|
+
function findMatchingProjects(projects, query) {
|
|
233
|
+
const queryLower = query.toLowerCase();
|
|
234
|
+
return projects.filter(p =>
|
|
235
|
+
p.name.toLowerCase().includes(queryLower) ||
|
|
236
|
+
p.path.toLowerCase().includes(queryLower)
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Check if branch is already checked out
|
|
241
|
+
function isBranchCheckedOut(branchName, cwd) {
|
|
242
|
+
const result = git('worktree list --porcelain', { silent: true, cwd });
|
|
243
|
+
if (!result.success) return false;
|
|
244
|
+
return result.output.includes(`branch refs/heads/${branchName}`);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Check if branch exists
|
|
248
|
+
function branchExists(branchName, cwd) {
|
|
249
|
+
const local = git(`show-ref --verify --quiet refs/heads/${branchName}`, { silent: true, cwd });
|
|
250
|
+
if (local.success) return 'local';
|
|
251
|
+
const remote = git(`show-ref --verify --quiet refs/remotes/origin/${branchName}`, { silent: true, cwd });
|
|
252
|
+
if (remote.success) return 'remote';
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Sanitize feature name to valid branch name
|
|
257
|
+
function sanitizeFeatureName(name) {
|
|
258
|
+
return name
|
|
259
|
+
.toLowerCase()
|
|
260
|
+
.replace(/[^a-z0-9-]/g, '-')
|
|
261
|
+
.replace(/-+/g, '-')
|
|
262
|
+
.replace(/^-|-$/g, '')
|
|
263
|
+
.slice(0, MAX_BRANCH_NAME_LENGTH);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// COMMANDS
|
|
267
|
+
|
|
268
|
+
function cmdInfo() {
|
|
269
|
+
const gitRoot = checkGitRepo();
|
|
270
|
+
checkGitVersion();
|
|
271
|
+
|
|
272
|
+
const projects = parseGitModules(gitRoot);
|
|
273
|
+
const isMonorepo = projects.length > 0;
|
|
274
|
+
const baseBranch = detectBaseBranch(gitRoot);
|
|
275
|
+
const dirtyState = checkDirtyState();
|
|
276
|
+
const dirtyDetails = dirtyState ? getDirtyStateDetails() : null;
|
|
277
|
+
const envFiles = findEnvFiles(gitRoot);
|
|
278
|
+
|
|
279
|
+
// For monorepo, also check each project for env files
|
|
280
|
+
const projectEnvFiles = {};
|
|
281
|
+
if (isMonorepo) {
|
|
282
|
+
projects.forEach(p => {
|
|
283
|
+
const projectDir = path.join(gitRoot, p.path);
|
|
284
|
+
if (fs.existsSync(projectDir)) {
|
|
285
|
+
const files = findEnvFiles(projectDir);
|
|
286
|
+
if (files.length > 0) {
|
|
287
|
+
projectEnvFiles[p.name] = files;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
output({
|
|
294
|
+
info: true,
|
|
295
|
+
repoType: isMonorepo ? 'monorepo' : 'standalone',
|
|
296
|
+
gitRoot,
|
|
297
|
+
baseBranch,
|
|
298
|
+
projects: isMonorepo ? projects : [],
|
|
299
|
+
envFiles,
|
|
300
|
+
projectEnvFiles: isMonorepo ? projectEnvFiles : {},
|
|
301
|
+
dirtyState,
|
|
302
|
+
dirtyDetails
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function cmdList() {
|
|
307
|
+
checkGitRepo();
|
|
308
|
+
const result = git('worktree list', { silent: true });
|
|
309
|
+
if (!result.success) {
|
|
310
|
+
outputError('WORKTREE_LIST_ERROR', 'Failed to list worktrees', {
|
|
311
|
+
suggestion: 'Ensure you are in a git repository'
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const worktrees = result.output.split('\n').filter(Boolean).map(line => {
|
|
316
|
+
const parts = line.split(/\s+/);
|
|
317
|
+
return {
|
|
318
|
+
path: parts[0],
|
|
319
|
+
commit: parts[1],
|
|
320
|
+
branch: parts[2]?.replace(/[\[\]]/g, '') || 'detached'
|
|
321
|
+
};
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
if (jsonOutput) {
|
|
325
|
+
console.log(JSON.stringify({ success: true, worktrees }, null, 2));
|
|
326
|
+
} else {
|
|
327
|
+
console.log('\n📂 Existing worktrees:');
|
|
328
|
+
worktrees.forEach(w => {
|
|
329
|
+
console.log(` ${w.path}`);
|
|
330
|
+
console.log(` Branch: ${w.branch} (${w.commit.slice(0, 7)})`);
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function cmdCreate() {
|
|
336
|
+
const gitRoot = checkGitRepo();
|
|
337
|
+
checkGitVersion();
|
|
338
|
+
|
|
339
|
+
const projects = parseGitModules(gitRoot);
|
|
340
|
+
const isMonorepo = projects.length > 0;
|
|
341
|
+
const warnings = [];
|
|
342
|
+
|
|
343
|
+
// Parse arguments based on repo type
|
|
344
|
+
// Monorepo: create <project> <feature>
|
|
345
|
+
// Standalone: create <feature>
|
|
346
|
+
let project, feature;
|
|
347
|
+
if (isMonorepo) {
|
|
348
|
+
project = arg1;
|
|
349
|
+
feature = arg2;
|
|
350
|
+
if (!project || !feature) {
|
|
351
|
+
outputError('MISSING_ARGS', 'Both project and feature are required for monorepo', {
|
|
352
|
+
suggestion: 'Usage: node worktree.cjs create <project> <feature> --prefix <type>',
|
|
353
|
+
availableProjects: projects.map(p => p.name)
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
} else {
|
|
357
|
+
feature = arg1;
|
|
358
|
+
if (!feature) {
|
|
359
|
+
outputError('MISSING_FEATURE', 'Feature name is required', {
|
|
360
|
+
suggestion: 'Usage: node worktree.cjs create <feature> --prefix <type>'
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Check dirty state
|
|
366
|
+
if (checkDirtyState()) {
|
|
367
|
+
const details = getDirtyStateDetails();
|
|
368
|
+
warnings.push(`Uncommitted changes: ${details.modified} modified, ${details.staged} staged, ${details.untracked} untracked`);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Determine working directory
|
|
372
|
+
let workDir = gitRoot;
|
|
373
|
+
let projectPath = '';
|
|
374
|
+
let projectName = '';
|
|
375
|
+
|
|
376
|
+
if (isMonorepo) {
|
|
377
|
+
const matches = findMatchingProjects(projects, project);
|
|
378
|
+
|
|
379
|
+
if (matches.length === 0) {
|
|
380
|
+
outputError('PROJECT_NOT_FOUND', `Project "${project}" not found`, {
|
|
381
|
+
suggestion: 'Check available projects with: node worktree.cjs info',
|
|
382
|
+
availableProjects: projects.map(p => p.name)
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if (matches.length > 1) {
|
|
387
|
+
outputError('MULTIPLE_PROJECTS_MATCH', `Multiple projects match "${project}"`, {
|
|
388
|
+
suggestion: 'Use AskUserQuestion to let user select one',
|
|
389
|
+
matchingProjects: matches.map(p => ({ name: p.name, path: p.path }))
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
projectPath = matches[0].path;
|
|
394
|
+
projectName = matches[0].name;
|
|
395
|
+
workDir = path.join(gitRoot, projectPath);
|
|
396
|
+
|
|
397
|
+
if (!fs.existsSync(workDir)) {
|
|
398
|
+
outputError('PROJECT_DIR_NOT_FOUND', `Project directory not found: ${workDir}`, {
|
|
399
|
+
suggestion: 'Initialize submodules: git submodule update --init'
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// Sanitize feature name
|
|
405
|
+
const sanitizedFeature = sanitizeFeatureName(feature);
|
|
406
|
+
if (sanitizedFeature !== feature.toLowerCase().replace(/\s+/g, '-')) {
|
|
407
|
+
warnings.push(`Feature name sanitized: "${feature}" → "${sanitizedFeature}"`);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Create branch name
|
|
411
|
+
const branchName = `${branchPrefix}/${sanitizedFeature}`;
|
|
412
|
+
|
|
413
|
+
// Detect base branch
|
|
414
|
+
const baseBranch = detectBaseBranch(workDir);
|
|
415
|
+
|
|
416
|
+
// Check if branch already checked out
|
|
417
|
+
if (isBranchCheckedOut(branchName, workDir)) {
|
|
418
|
+
outputError('BRANCH_CHECKED_OUT', `Branch "${branchName}" is already checked out in another worktree`, {
|
|
419
|
+
suggestion: 'Use a different feature name or remove the existing worktree'
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// Determine worktree path
|
|
424
|
+
let worktreesDir, worktreeName;
|
|
425
|
+
if (isMonorepo) {
|
|
426
|
+
worktreesDir = path.join(gitRoot, 'worktrees');
|
|
427
|
+
worktreeName = `${projectName}-${sanitizedFeature}`;
|
|
428
|
+
} else {
|
|
429
|
+
const repoName = path.basename(gitRoot);
|
|
430
|
+
worktreesDir = path.join(path.dirname(gitRoot), 'worktrees');
|
|
431
|
+
worktreeName = `${repoName}-${sanitizedFeature}`;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const worktreePath = path.join(worktreesDir, worktreeName);
|
|
435
|
+
|
|
436
|
+
// Check if worktree already exists
|
|
437
|
+
if (fs.existsSync(worktreePath)) {
|
|
438
|
+
outputError('WORKTREE_EXISTS', `Worktree already exists: ${worktreePath}`, {
|
|
439
|
+
suggestion: `To use: cd ${worktreePath} && claude\nTo remove: git worktree remove ${worktreePath}`
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Check if branch exists
|
|
444
|
+
const branchStatus = branchExists(branchName, workDir);
|
|
445
|
+
|
|
446
|
+
// Dry-run mode: show what would be done
|
|
447
|
+
if (dryRun) {
|
|
448
|
+
output({
|
|
449
|
+
success: true,
|
|
450
|
+
dryRun: true,
|
|
451
|
+
message: 'Dry run - no changes made',
|
|
452
|
+
wouldCreate: {
|
|
453
|
+
worktreePath,
|
|
454
|
+
branch: branchName,
|
|
455
|
+
baseBranch,
|
|
456
|
+
branchExists: !!branchStatus,
|
|
457
|
+
project: isMonorepo ? projectName : null,
|
|
458
|
+
envFilesToCopy: envFilesToCopy.length > 0 ? envFilesToCopy : undefined
|
|
459
|
+
},
|
|
460
|
+
warnings: warnings.length > 0 ? warnings : undefined
|
|
461
|
+
});
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Create worktrees directory
|
|
466
|
+
try {
|
|
467
|
+
fs.mkdirSync(worktreesDir, { recursive: true });
|
|
468
|
+
} catch (err) {
|
|
469
|
+
outputError('MKDIR_FAILED', `Failed to create worktrees directory: ${worktreesDir}`, {
|
|
470
|
+
suggestion: 'Check write permissions'
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Fetch remote branch if needed
|
|
475
|
+
if (branchStatus === 'remote') {
|
|
476
|
+
const fetchResult = git(`fetch origin ${branchName}`, { silent: true, cwd: workDir });
|
|
477
|
+
if (!fetchResult.success) {
|
|
478
|
+
outputError('FETCH_FAILED', `Failed to fetch branch from remote: ${branchName}`, {
|
|
479
|
+
suggestion: 'Check network connection and remote repository access'
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Create worktree
|
|
485
|
+
let createResult;
|
|
486
|
+
if (branchStatus) {
|
|
487
|
+
createResult = git(`worktree add "${worktreePath}" ${branchName}`, { cwd: workDir });
|
|
488
|
+
} else {
|
|
489
|
+
createResult = git(`worktree add -b ${branchName} "${worktreePath}" ${baseBranch}`, { cwd: workDir });
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (!createResult.success) {
|
|
493
|
+
outputError('WORKTREE_CREATE_FAILED', `Failed to create worktree`, {
|
|
494
|
+
suggestion: createResult.stderr || createResult.error,
|
|
495
|
+
gitError: createResult.stderr
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// Copy env files if specified
|
|
500
|
+
const envFilesCopied = [];
|
|
501
|
+
if (envFilesToCopy.length > 0) {
|
|
502
|
+
const sourceDir = isMonorepo ? workDir : gitRoot;
|
|
503
|
+
envFilesToCopy.forEach(envFile => {
|
|
504
|
+
const sourcePath = path.join(sourceDir, envFile);
|
|
505
|
+
const destPath = path.join(worktreePath, envFile);
|
|
506
|
+
if (fs.existsSync(sourcePath)) {
|
|
507
|
+
try {
|
|
508
|
+
fs.copyFileSync(sourcePath, destPath);
|
|
509
|
+
envFilesCopied.push(envFile);
|
|
510
|
+
} catch (err) {
|
|
511
|
+
warnings.push(`Failed to copy ${envFile}: ${err.message}`);
|
|
512
|
+
}
|
|
513
|
+
} else {
|
|
514
|
+
warnings.push(`Env file not found: ${envFile}`);
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
output({
|
|
520
|
+
success: true,
|
|
521
|
+
message: 'Worktree created successfully!',
|
|
522
|
+
worktreePath,
|
|
523
|
+
branch: branchName,
|
|
524
|
+
baseBranch,
|
|
525
|
+
project: isMonorepo ? projectName : null,
|
|
526
|
+
envFilesCopied,
|
|
527
|
+
warnings: warnings.length > 0 ? warnings : undefined
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
function cmdRemove() {
|
|
532
|
+
if (!arg1) {
|
|
533
|
+
outputError('MISSING_WORKTREE', 'Worktree name or path is required', {
|
|
534
|
+
suggestion: 'Usage: node worktree.cjs remove <name-or-path>\nUse "node worktree.cjs list" to see available worktrees'
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const gitRoot = checkGitRepo();
|
|
539
|
+
checkGitVersion();
|
|
540
|
+
|
|
541
|
+
// Get list of worktrees
|
|
542
|
+
const result = git('worktree list --porcelain', { silent: true });
|
|
543
|
+
if (!result.success) {
|
|
544
|
+
outputError('WORKTREE_LIST_ERROR', 'Failed to list worktrees');
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Parse worktrees
|
|
548
|
+
const worktrees = [];
|
|
549
|
+
let current = {};
|
|
550
|
+
result.output.split('\n').forEach(line => {
|
|
551
|
+
if (line.startsWith('worktree ')) {
|
|
552
|
+
if (current.path) worktrees.push(current);
|
|
553
|
+
current = { path: line.replace('worktree ', '') };
|
|
554
|
+
} else if (line.startsWith('branch ')) {
|
|
555
|
+
current.branch = line.replace('branch refs/heads/', '');
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
if (current.path) worktrees.push(current);
|
|
559
|
+
|
|
560
|
+
// Find matching worktree
|
|
561
|
+
const searchTerm = arg1.toLowerCase();
|
|
562
|
+
const matches = worktrees.filter(w => {
|
|
563
|
+
const name = path.basename(w.path).toLowerCase();
|
|
564
|
+
const fullPath = w.path.toLowerCase();
|
|
565
|
+
return name.includes(searchTerm) || fullPath.includes(searchTerm) ||
|
|
566
|
+
(w.branch && w.branch.toLowerCase().includes(searchTerm));
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
// Exclude main worktree (bare .git or the primary checkout)
|
|
570
|
+
const removableMatches = matches.filter(w => !w.path.includes('.git/'));
|
|
571
|
+
|
|
572
|
+
if (removableMatches.length === 0) {
|
|
573
|
+
outputError('WORKTREE_NOT_FOUND', `No worktree matching "${arg1}" found`, {
|
|
574
|
+
suggestion: 'Use "node worktree.cjs list" to see available worktrees',
|
|
575
|
+
availableWorktrees: worktrees.filter(w => !w.path.includes('.git/')).map(w => path.basename(w.path))
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
if (removableMatches.length > 1) {
|
|
580
|
+
outputError('MULTIPLE_WORKTREES_MATCH', `Multiple worktrees match "${arg1}"`, {
|
|
581
|
+
suggestion: 'Be more specific or use full path',
|
|
582
|
+
matchingWorktrees: removableMatches.map(w => ({ name: path.basename(w.path), path: w.path, branch: w.branch }))
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
const worktree = removableMatches[0];
|
|
587
|
+
const worktreePath = worktree.path;
|
|
588
|
+
const branchName = worktree.branch;
|
|
589
|
+
|
|
590
|
+
// Dry-run mode
|
|
591
|
+
if (dryRun) {
|
|
592
|
+
output({
|
|
593
|
+
success: true,
|
|
594
|
+
dryRun: true,
|
|
595
|
+
message: 'Dry run - no changes made',
|
|
596
|
+
wouldRemove: {
|
|
597
|
+
worktreePath,
|
|
598
|
+
branch: branchName,
|
|
599
|
+
deleteBranch: !!branchName
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Remove worktree
|
|
606
|
+
const removeResult = git(`worktree remove "${worktreePath}" --force`, { silent: true });
|
|
607
|
+
if (!removeResult.success) {
|
|
608
|
+
outputError('WORKTREE_REMOVE_FAILED', `Failed to remove worktree: ${worktreePath}`, {
|
|
609
|
+
suggestion: removeResult.stderr || 'Check if the worktree has uncommitted changes',
|
|
610
|
+
gitError: removeResult.stderr
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// Delete branch if it exists
|
|
615
|
+
let branchDeleted = false;
|
|
616
|
+
if (branchName) {
|
|
617
|
+
const deleteResult = git(`branch -d "${branchName}"`, { silent: true });
|
|
618
|
+
if (deleteResult.success) {
|
|
619
|
+
branchDeleted = true;
|
|
620
|
+
} else {
|
|
621
|
+
// Try force delete if normal delete fails
|
|
622
|
+
const forceDeleteResult = git(`branch -D "${branchName}"`, { silent: true });
|
|
623
|
+
branchDeleted = forceDeleteResult.success;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
output({
|
|
628
|
+
success: true,
|
|
629
|
+
message: 'Worktree removed successfully!',
|
|
630
|
+
removedPath: worktreePath,
|
|
631
|
+
branchDeleted: branchDeleted ? branchName : null,
|
|
632
|
+
branchKept: !branchDeleted && branchName ? branchName : null
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// Main
|
|
637
|
+
function main() {
|
|
638
|
+
switch (command) {
|
|
639
|
+
case 'create':
|
|
640
|
+
cmdCreate();
|
|
641
|
+
break;
|
|
642
|
+
case 'remove':
|
|
643
|
+
cmdRemove();
|
|
644
|
+
break;
|
|
645
|
+
case 'info':
|
|
646
|
+
cmdInfo();
|
|
647
|
+
break;
|
|
648
|
+
case 'list':
|
|
649
|
+
cmdList();
|
|
650
|
+
break;
|
|
651
|
+
default:
|
|
652
|
+
outputError('UNKNOWN_COMMAND', `Unknown command: ${command || '(none)'}`, {
|
|
653
|
+
suggestion: 'Available commands: create, remove, info, list'
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
main();
|