specweave 0.4.1 ā 0.6.3
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/.claude-plugin/README.md +312 -0
- package/.claude-plugin/marketplace.json +210 -0
- package/CLAUDE.md +952 -609
- package/README.md +179 -761
- package/bin/install-agents.sh +1 -1
- package/bin/install-commands.sh +66 -14
- package/bin/install-hooks.sh +1 -1
- package/bin/install-skills.sh +1 -1
- package/bin/specweave.js +2 -0
- package/dist/adapters/claude/adapter.d.ts +49 -11
- package/dist/adapters/claude/adapter.d.ts.map +1 -1
- package/dist/adapters/claude/adapter.js +175 -42
- package/dist/adapters/claude/adapter.js.map +1 -1
- package/dist/adapters/copilot/adapter.d.ts +20 -2
- package/dist/adapters/copilot/adapter.d.ts.map +1 -1
- package/dist/adapters/copilot/adapter.js +117 -7
- package/dist/adapters/copilot/adapter.js.map +1 -1
- package/dist/adapters/cursor/adapter.d.ts +18 -0
- package/dist/adapters/cursor/adapter.d.ts.map +1 -1
- package/dist/adapters/cursor/adapter.js +55 -3
- package/dist/adapters/cursor/adapter.js.map +1 -1
- package/dist/adapters/generic/adapter.d.ts +18 -0
- package/dist/adapters/generic/adapter.d.ts.map +1 -1
- package/dist/adapters/generic/adapter.js +55 -3
- package/dist/adapters/generic/adapter.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +521 -185
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/install.d.ts +2 -0
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +28 -25
- package/dist/cli/commands/install.js.map +1 -1
- package/dist/cli/commands/list.d.ts +2 -0
- package/dist/cli/commands/list.d.ts.map +1 -1
- package/dist/cli/commands/list.js +26 -24
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/plugin.d.ts +23 -6
- package/dist/cli/commands/plugin.d.ts.map +1 -1
- package/dist/cli/commands/plugin.js +92 -66
- package/dist/cli/commands/plugin.js.map +1 -1
- package/dist/core/i18n/language-detector.d.ts +29 -0
- package/dist/core/i18n/language-detector.d.ts.map +1 -0
- package/dist/core/i18n/language-detector.js +143 -0
- package/dist/core/i18n/language-detector.js.map +1 -0
- package/dist/core/i18n/language-manager.d.ts +101 -0
- package/dist/core/i18n/language-manager.d.ts.map +1 -0
- package/dist/core/i18n/language-manager.js +232 -0
- package/dist/core/i18n/language-manager.js.map +1 -0
- package/dist/core/i18n/language-registry.d.ts +44 -0
- package/dist/core/i18n/language-registry.d.ts.map +1 -0
- package/dist/core/i18n/language-registry.js +234 -0
- package/dist/core/i18n/language-registry.js.map +1 -0
- package/dist/core/i18n/locale-manager.d.ts +62 -0
- package/dist/core/i18n/locale-manager.d.ts.map +1 -0
- package/dist/core/i18n/locale-manager.js +137 -0
- package/dist/core/i18n/locale-manager.js.map +1 -0
- package/dist/core/i18n/system-prompt-injector.d.ts +33 -0
- package/dist/core/i18n/system-prompt-injector.d.ts.map +1 -0
- package/dist/core/i18n/system-prompt-injector.js +131 -0
- package/dist/core/i18n/system-prompt-injector.js.map +1 -0
- package/dist/core/i18n/types.d.ts +151 -0
- package/dist/core/i18n/types.d.ts.map +1 -0
- package/dist/core/i18n/types.js +11 -0
- package/dist/core/i18n/types.js.map +1 -0
- package/dist/core/increment-status.d.ts +72 -0
- package/dist/core/increment-status.d.ts.map +1 -0
- package/dist/core/increment-status.js +227 -0
- package/dist/core/increment-status.js.map +1 -0
- package/dist/core/plugin-loader.d.ts +33 -13
- package/dist/core/plugin-loader.d.ts.map +1 -1
- package/dist/core/plugin-loader.js +145 -43
- package/dist/core/plugin-loader.js.map +1 -1
- package/dist/core/types/config.d.ts +51 -0
- package/dist/core/types/config.d.ts.map +1 -0
- package/dist/core/types/config.js +21 -0
- package/dist/core/types/config.js.map +1 -0
- package/dist/core/types/plugin.d.ts +73 -42
- package/dist/core/types/plugin.d.ts.map +1 -1
- package/dist/core/types/plugin.js +4 -3
- package/dist/core/types/plugin.js.map +1 -1
- package/dist/hooks/lib/sync-living-docs.d.ts +27 -0
- package/dist/hooks/lib/sync-living-docs.d.ts.map +1 -0
- package/dist/hooks/lib/sync-living-docs.js +116 -0
- package/dist/hooks/lib/sync-living-docs.js.map +1 -0
- package/dist/hooks/lib/translate-living-docs.d.ts +13 -0
- package/dist/hooks/lib/translate-living-docs.d.ts.map +1 -0
- package/dist/hooks/lib/translate-living-docs.js +166 -0
- package/dist/hooks/lib/translate-living-docs.js.map +1 -0
- package/dist/hooks/lib/update-tasks-md.d.ts +29 -0
- package/dist/hooks/lib/update-tasks-md.d.ts.map +1 -0
- package/dist/hooks/lib/update-tasks-md.js +203 -0
- package/dist/hooks/lib/update-tasks-md.js.map +1 -0
- package/dist/integrations/jira/jira-incremental-mapper.js.map +1 -1
- package/dist/integrations/jira/jira-mapper.js.map +1 -1
- package/dist/locales/de/.gitkeep +0 -0
- package/dist/locales/de/cli.json +108 -0
- package/dist/locales/en/cli.json +285 -0
- package/dist/locales/en/errors.json +7 -0
- package/dist/locales/en/templates.json +6 -0
- package/dist/locales/es/.gitkeep +0 -0
- package/dist/locales/es/cli.json +41 -0
- package/dist/locales/fr/.gitkeep +0 -0
- package/dist/locales/fr/cli.json +108 -0
- package/dist/locales/ja/.gitkeep +0 -0
- package/dist/locales/ja/cli.json +108 -0
- package/dist/locales/ko/.gitkeep +0 -0
- package/dist/locales/ko/cli.json +108 -0
- package/dist/locales/pt/.gitkeep +0 -0
- package/dist/locales/pt/cli.json +108 -0
- package/dist/locales/ru/.gitkeep +0 -0
- package/dist/locales/ru/cli.json +269 -0
- package/dist/locales/zh/.gitkeep +0 -0
- package/dist/locales/zh/cli.json +108 -0
- package/dist/plugins/specweave-github/lib/github-client.d.ts +86 -0
- package/dist/plugins/specweave-github/lib/github-client.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-client.js +275 -0
- package/dist/plugins/specweave-github/lib/github-client.js.map +1 -0
- package/dist/plugins/specweave-github/lib/index.d.ts +10 -0
- package/dist/plugins/specweave-github/lib/index.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/index.js +10 -0
- package/dist/plugins/specweave-github/lib/index.js.map +1 -0
- package/dist/plugins/specweave-github/lib/subtask-sync.d.ts +51 -0
- package/dist/plugins/specweave-github/lib/subtask-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/subtask-sync.js +147 -0
- package/dist/plugins/specweave-github/lib/subtask-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/task-parser.d.ts +37 -0
- package/dist/plugins/specweave-github/lib/task-parser.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/task-parser.js +211 -0
- package/dist/plugins/specweave-github/lib/task-parser.js.map +1 -0
- package/dist/plugins/specweave-github/lib/task-sync.d.ts +51 -0
- package/dist/plugins/specweave-github/lib/task-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/task-sync.js +332 -0
- package/dist/plugins/specweave-github/lib/task-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/types.d.ts +80 -0
- package/dist/plugins/specweave-github/lib/types.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/types.js +5 -0
- package/dist/plugins/specweave-github/lib/types.js.map +1 -0
- package/dist/utils/agents-md-compiler.d.ts +68 -0
- package/dist/utils/agents-md-compiler.d.ts.map +1 -0
- package/dist/utils/agents-md-compiler.js +420 -0
- package/dist/utils/agents-md-compiler.js.map +1 -0
- package/dist/utils/execFileNoThrow.d.ts +97 -0
- package/dist/utils/execFileNoThrow.d.ts.map +1 -0
- package/dist/utils/execFileNoThrow.js +130 -0
- package/dist/utils/execFileNoThrow.js.map +1 -0
- package/dist/utils/generate-skills-index.js +4 -4
- package/dist/utils/generate-skills-index.js.map +1 -1
- package/package.json +13 -14
- package/plugins/.specweave/logs/hooks-debug.log +24 -0
- package/plugins/.specweave/logs/last-hook-fire +1 -0
- package/plugins/.specweave/logs/last-todowrite-time +1 -0
- package/plugins/.specweave/logs/tasks.log +6 -0
- package/plugins/specweave/.claude-plugin/plugin.json +22 -0
- package/{src ā plugins/specweave}/agents/pm/AGENT.md +80 -0
- package/plugins/specweave/agents/translator/AGENT.md +282 -0
- package/{src ā plugins/specweave}/commands/README.md +11 -11
- package/{src/commands/specweave.costs.md ā plugins/specweave/commands/costs.md} +8 -8
- package/{src/commands/specweave.do.md ā plugins/specweave/commands/do.md} +35 -8
- package/{src/commands/specweave.done.md ā plugins/specweave/commands/done.md} +1 -1
- package/{src/commands/specweave.inc.md ā plugins/specweave/commands/inc.md} +1 -1
- package/{src/commands/specweave.increment.md ā plugins/specweave/commands/increment.md} +84 -19
- package/{src/commands/specweave.next.md ā plugins/specweave/commands/next.md} +1 -1
- package/{src/commands/specweave.progress.md ā plugins/specweave/commands/progress.md} +1 -1
- package/{src ā plugins/specweave}/commands/specweave.md +57 -25
- package/{src/commands/specweave.sync-docs.md ā plugins/specweave/commands/sync-docs.md} +6 -6
- package/plugins/specweave/commands/translate.md +425 -0
- package/{src/commands/specweave.validate.md ā plugins/specweave/commands/validate.md} +2 -2
- package/plugins/specweave/hooks/hooks.json +15 -0
- package/plugins/specweave/hooks/post-task-completion.sh +265 -0
- package/plugins/specweave/skills/SKILLS-INDEX.md +229 -0
- package/{src ā plugins/specweave}/skills/brownfield-analyzer/SKILL.md +66 -24
- package/{src ā plugins/specweave}/skills/context-loader/SKILL.md +1 -1
- package/plugins/specweave/skills/context-optimizer/SKILL.md +588 -0
- package/plugins/specweave/skills/docs-updater/SKILL.md +0 -0
- package/{src ā plugins/specweave}/skills/increment-planner/SKILL.md +81 -4
- package/plugins/specweave/skills/plugin-detector/SKILL.md +211 -0
- package/{src ā plugins/specweave}/skills/project-kickstarter/SKILL.md +7 -7
- package/plugins/specweave/skills/rfc-generator/SKILL.md +369 -0
- package/{src ā plugins/specweave}/skills/specweave-detector/SKILL.md +2 -2
- package/plugins/specweave/skills/specweave-framework/SKILL.md +498 -0
- package/plugins/specweave/skills/specweave-framework/test-cases/test-1-increment-naming.yaml +11 -0
- package/plugins/specweave/skills/specweave-framework/test-cases/test-2-source-of-truth.yaml +11 -0
- package/plugins/specweave/skills/specweave-framework/test-cases/test-3-increment-discipline.yaml +12 -0
- package/plugins/specweave/skills/specweave-framework/test-cases/test-4-file-placement.yaml +11 -0
- package/{src ā plugins/specweave}/skills/tdd-workflow/SKILL.md +21 -21
- package/plugins/specweave/skills/translator/SKILL.md +172 -0
- package/plugins/specweave-ado/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-alternatives/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-alternatives/skills/bmad-method-expert/SKILL.md +626 -0
- package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/analyze-project.js +318 -0
- package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/check-setup.js +208 -0
- package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/generate-template.js +1149 -0
- package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/validate-documents.js +340 -0
- package/plugins/specweave-alternatives/skills/spec-kit-expert/SKILL.md +1010 -0
- package/plugins/specweave-backend/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-cost-optimizer/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-diagrams/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-docs/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-docs/skills/docusaurus/SKILL.md +526 -0
- package/plugins/specweave-figma/.claude-plugin/.mcp.json +12 -0
- package/plugins/specweave-figma/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-figma/ARCHITECTURE.md +453 -0
- package/plugins/specweave-figma/README.md +728 -0
- package/plugins/specweave-figma/skills/figma-to-code/SKILL.md +632 -0
- package/plugins/specweave-figma/skills/figma-to-code/test-1-token-generation.yaml +29 -0
- package/plugins/specweave-figma/skills/figma-to-code/test-2-component-generation.yaml +27 -0
- package/plugins/specweave-figma/skills/figma-to-code/test-3-typescript-generation.yaml +28 -0
- package/plugins/specweave-frontend/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-github/.claude-plugin/plugin.json +19 -0
- package/plugins/specweave-github/agents/github-manager/AGENT.md +651 -0
- package/plugins/specweave-github/commands/github-close-issue.md +418 -0
- package/plugins/specweave-github/commands/github-create-issue.md +307 -0
- package/plugins/specweave-github/commands/github-status.md +533 -0
- package/plugins/specweave-github/commands/github-sync-tasks.md +530 -0
- package/plugins/specweave-github/commands/github-sync.md +443 -0
- package/plugins/specweave-github/lib/github-client.ts +330 -0
- package/plugins/specweave-github/lib/index.ts +10 -0
- package/plugins/specweave-github/lib/subtask-sync.ts +225 -0
- package/plugins/specweave-github/lib/task-parser.ts +246 -0
- package/plugins/specweave-github/lib/task-sync.ts +402 -0
- package/plugins/specweave-github/lib/types.ts +86 -0
- package/plugins/specweave-github/skills/github-issue-tracker/SKILL.md +497 -0
- package/plugins/specweave-github/skills/github-sync/SKILL.md +461 -0
- package/plugins/specweave-infrastructure/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-jira/.claude-plugin/plugin.json +8 -0
- package/{src ā plugins/specweave-jira}/commands/specweave.sync-jira.md +18 -18
- package/plugins/specweave-kubernetes/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-ml/.claude-plugin/plugin.json +38 -0
- package/plugins/specweave-ml/README.md +885 -0
- package/plugins/specweave-ml/agents/ml-engineer/AGENT.md +402 -0
- package/plugins/specweave-ml/commands/ml-deploy.md +116 -0
- package/plugins/specweave-ml/commands/ml-evaluate.md +87 -0
- package/plugins/specweave-ml/commands/ml-explain.md +83 -0
- package/plugins/specweave-ml/skills/anomaly-detector/SKILL.md +559 -0
- package/plugins/specweave-ml/skills/automl-optimizer/SKILL.md +485 -0
- package/plugins/specweave-ml/skills/cv-pipeline-builder/SKILL.md +157 -0
- package/plugins/specweave-ml/skills/data-visualizer/SKILL.md +521 -0
- package/plugins/specweave-ml/skills/experiment-tracker/SKILL.md +535 -0
- package/plugins/specweave-ml/skills/feature-engineer/SKILL.md +566 -0
- package/plugins/specweave-ml/skills/ml-deployment-helper/SKILL.md +345 -0
- package/plugins/specweave-ml/skills/ml-pipeline-orchestrator/SKILL.md +518 -0
- package/plugins/specweave-ml/skills/model-evaluator/SKILL.md +155 -0
- package/plugins/specweave-ml/skills/model-explainer/SKILL.md +227 -0
- package/plugins/specweave-ml/skills/model-registry/SKILL.md +541 -0
- package/plugins/specweave-ml/skills/nlp-pipeline-builder/SKILL.md +180 -0
- package/plugins/specweave-ml/skills/time-series-forecaster/SKILL.md +569 -0
- package/plugins/specweave-payments/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-testing/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-tooling/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-ui/.claude-plugin/plugin.json +26 -0
- package/plugins/specweave-ui/.mcp.json +14 -0
- package/plugins/specweave-ui/README.md +386 -0
- package/src/adapters/claude/adapter.ts +193 -46
- package/src/adapters/copilot/adapter.ts +132 -7
- package/src/adapters/cursor/adapter.ts +62 -3
- package/src/adapters/generic/adapter.ts +62 -3
- package/src/templates/AGENTS.md.template +170 -1
- package/src/templates/CLAUDE.md.template +122 -24
- package/src/templates/tasks.md.template +261 -0
- package/src/agents/ml-engineer/AGENT.md +0 -150
- package/src/commands/specweave.sync-github.md +0 -269
- package/src/hooks/post-task-completion.sh +0 -121
- package/src/skills/SKILLS-INDEX.md +0 -444
- package/src/skills/github-sync/SKILL.md +0 -234
- /package/{src ā plugins/specweave}/agents/architect/AGENT.md +0 -0
- /package/{src ā plugins/specweave}/agents/code-reviewer.md +0 -0
- /package/{src ā plugins/specweave}/agents/docs-writer/AGENT.md +0 -0
- /package/{src ā plugins/specweave}/agents/performance/AGENT.md +0 -0
- /package/{src ā plugins/specweave}/agents/qa-lead/AGENT.md +0 -0
- /package/{src ā plugins/specweave}/agents/security/AGENT.md +0 -0
- /package/{src ā plugins/specweave}/agents/tdd-orchestrator/AGENT.md +0 -0
- /package/{src ā plugins/specweave}/agents/tech-lead/AGENT.md +0 -0
- /package/{src/commands/specweave.list-increments.md ā plugins/specweave/commands/list-increments.md} +0 -0
- /package/{src/commands/specweave.tdd-cycle.md ā plugins/specweave/commands/tdd-cycle.md} +0 -0
- /package/{src/commands/specweave.tdd-green.md ā plugins/specweave/commands/tdd-green.md} +0 -0
- /package/{src/commands/specweave.tdd-red.md ā plugins/specweave/commands/tdd-red.md} +0 -0
- /package/{src/commands/specweave.tdd-refactor.md ā plugins/specweave/commands/tdd-refactor.md} +0 -0
- /package/{src ā plugins/specweave}/hooks/README.md +0 -0
- /package/{src ā plugins/specweave}/hooks/docs-changed.sh +0 -0
- /package/{src ā plugins/specweave}/hooks/human-input-required.sh +0 -0
- /package/{src ā plugins/specweave}/hooks/post-increment-plugin-detect.sh +0 -0
- /package/{src ā plugins/specweave}/hooks/pre-implementation.sh +0 -0
- /package/{src ā plugins/specweave}/hooks/pre-task-plugin-detect.sh +0 -0
- /package/{src ā plugins/specweave}/skills/brownfield-onboarder/SKILL.md +0 -0
- /package/{src ā plugins/specweave}/skills/docs-updater/README.md +0 -0
- /package/{src ā plugins/specweave}/skills/increment-planner/scripts/feature-utils.js +0 -0
- /package/{src ā plugins/specweave}/skills/increment-quality-judge/SKILL.md +0 -0
- /package/{src ā plugins/specweave}/skills/project-kickstarter/test-cases/test-1-high-confidence-full-product.yaml +0 -0
- /package/{src ā plugins/specweave}/skills/project-kickstarter/test-cases/test-2-medium-confidence-partial.yaml +0 -0
- /package/{src ā plugins/specweave}/skills/project-kickstarter/test-cases/test-3-low-confidence-technical-question.yaml +0 -0
- /package/{src ā plugins/specweave}/skills/project-kickstarter/test-cases/test-4-opt-out-explicit.yaml +0 -0
- /package/{src ā plugins/specweave}/skills/role-orchestrator/README.md +0 -0
- /package/{src ā plugins/specweave}/skills/role-orchestrator/SKILL.md +0 -0
- /package/{src ā plugins/specweave}/skills/task-builder/README.md +0 -0
- /package/{src ā plugins/specweave-ado}/skills/ado-sync/README.md +0 -0
- /package/{src ā plugins/specweave-ado}/skills/ado-sync/SKILL.md +0 -0
- /package/{src ā plugins/specweave-ado}/skills/specweave-ado-mapper/SKILL.md +0 -0
- /package/{src ā plugins/specweave-backend}/agents/database-optimizer/AGENT.md +0 -0
- /package/{src ā plugins/specweave-backend}/skills/dotnet-backend/SKILL.md +0 -0
- /package/{src ā plugins/specweave-backend}/skills/nodejs-backend/SKILL.md +0 -0
- /package/{src ā plugins/specweave-backend}/skills/python-backend/SKILL.md +0 -0
- /package/{src ā plugins/specweave-cost-optimizer}/skills/cost-optimizer/SKILL.md +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/AGENT.md +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/templates/c4-component-template.mmd +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/templates/c4-container-template.mmd +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/templates/c4-context-template.mmd +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/templates/deployment-template.mmd +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/templates/er-diagram-template.mmd +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/templates/sequence-template.mmd +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/test-cases/test-1-c4-context.yaml +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/test-cases/test-2-sequence.yaml +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/test-cases/test-3-er-diagram.yaml +0 -0
- /package/{src ā plugins/specweave-diagrams}/skills/diagrams-architect/SKILL.md +0 -0
- /package/{src ā plugins/specweave-diagrams}/skills/diagrams-generator/SKILL.md +0 -0
- /package/{src ā plugins/specweave-docs}/skills/spec-driven-brainstorming/README.md +0 -0
- /package/{src ā plugins/specweave-docs}/skills/spec-driven-brainstorming/SKILL.md +0 -0
- /package/{src ā plugins/specweave-docs}/skills/spec-driven-debugging/README.md +0 -0
- /package/{src ā plugins/specweave-docs}/skills/spec-driven-debugging/SKILL.md +0 -0
- /package/{src ā plugins/specweave-frontend}/skills/design-system-architect/SKILL.md +0 -0
- /package/{src ā plugins/specweave-frontend}/skills/frontend/SKILL.md +0 -0
- /package/{src ā plugins/specweave-frontend}/skills/nextjs/SKILL.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/devops/AGENT.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/network-engineer/AGENT.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/observability-engineer/AGENT.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/performance-engineer/AGENT.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/AGENT.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/modules/backend-diagnostics.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/modules/database-diagnostics.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/modules/infrastructure.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/modules/monitoring.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/modules/security-incidents.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/modules/ui-diagnostics.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/01-high-cpu-usage.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/02-database-deadlock.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/03-memory-leak.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/04-slow-api-response.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/05-ddos-attack.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/06-disk-full.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/07-service-down.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/08-data-corruption.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/09-cascade-failure.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/10-rate-limit-exceeded.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/scripts/health-check.sh +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/scripts/log-analyzer.py +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/scripts/metrics-collector.sh +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/scripts/trace-analyzer.js +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/templates/incident-report.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/templates/mitigation-plan.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/templates/post-mortem.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/templates/runbook-template.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/commands/specweave.monitor-setup.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/commands/specweave.slo-implement.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/skills/distributed-tracing/SKILL.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/skills/grafana-dashboards/SKILL.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/skills/hetzner-provisioner/README.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/skills/hetzner-provisioner/SKILL.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/skills/prometheus-configuration/SKILL.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/skills/slo-implementation/SKILL.md +0 -0
- /package/{src ā plugins/specweave-jira}/skills/jira-sync/README.md +0 -0
- /package/{src ā plugins/specweave-jira}/skills/jira-sync/SKILL.md +0 -0
- /package/{src ā plugins/specweave-jira}/skills/specweave-jira-mapper/SKILL.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/agents/kubernetes-architect/AGENT.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/gitops-workflow/SKILL.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/gitops-workflow/references/argocd-setup.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/gitops-workflow/references/sync-policies.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/helm-chart-scaffolding/SKILL.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/helm-chart-scaffolding/assets/Chart.yaml.template +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/helm-chart-scaffolding/assets/values.yaml.template +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/helm-chart-scaffolding/references/chart-structure.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/helm-chart-scaffolding/scripts/validate-chart.sh +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-manifest-generator/SKILL.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-manifest-generator/assets/configmap-template.yaml +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-manifest-generator/assets/deployment-template.yaml +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-manifest-generator/assets/service-template.yaml +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-manifest-generator/references/deployment-spec.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-manifest-generator/references/service-spec.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-security-policies/SKILL.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-security-policies/assets/network-policy-template.yaml +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-security-policies/references/rbac-patterns.md +0 -0
- /package/{src ā plugins/specweave-ml}/agents/data-scientist/AGENT.md +0 -0
- /package/{src ā plugins/specweave-ml}/agents/mlops-engineer/AGENT.md +0 -0
- /package/{src ā plugins/specweave-ml}/commands/specweave.ml-pipeline.md +0 -0
- /package/{src ā plugins/specweave-ml}/skills/ml-pipeline-workflow/SKILL.md +0 -0
- /package/{src ā plugins/specweave-payments}/agents/payment-integration/AGENT.md +0 -0
- /package/{src ā plugins/specweave-payments}/skills/billing-automation/SKILL.md +0 -0
- /package/{src ā plugins/specweave-payments}/skills/paypal-integration/SKILL.md +0 -0
- /package/{src ā plugins/specweave-payments}/skills/pci-compliance/SKILL.md +0 -0
- /package/{src ā plugins/specweave-payments}/skills/stripe-integration/SKILL.md +0 -0
- /package/{src ā plugins/specweave-testing}/skills/e2e-playwright/README.md +0 -0
- /package/{src ā plugins/specweave-testing}/skills/e2e-playwright/SKILL.md +0 -0
- /package/{src ā plugins/specweave-testing}/skills/e2e-playwright/execute.js +0 -0
- /package/{src ā plugins/specweave-testing}/skills/e2e-playwright/lib/utils.js +0 -0
- /package/{src ā plugins/specweave-testing}/skills/e2e-playwright/package.json +0 -0
- /package/{src ā plugins/specweave-tooling}/skills/skill-creator/LICENSE.txt +0 -0
- /package/{src ā plugins/specweave-tooling}/skills/skill-creator/SKILL.md +0 -0
- /package/{src ā plugins/specweave-tooling}/skills/skill-creator/scripts/init_skill.py +0 -0
- /package/{src ā plugins/specweave-tooling}/skills/skill-creator/scripts/package_skill.py +0 -0
- /package/{src ā plugins/specweave-tooling}/skills/skill-creator/scripts/quick_validate.py +0 -0
- /package/{src ā plugins/specweave-tooling}/skills/skill-router/SKILL.md +0 -0
|
@@ -3,15 +3,29 @@ import * as path from 'path';
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import ora from 'ora';
|
|
5
5
|
import inquirer from 'inquirer';
|
|
6
|
-
import {
|
|
6
|
+
import { execFileNoThrowSync, isCommandAvailableSync } from '../../utils/execFileNoThrow.js';
|
|
7
7
|
import { AdapterLoader } from '../../adapters/adapter-loader.js';
|
|
8
8
|
import { ClaudeMdGenerator } from '../../adapters/claude-md-generator.js';
|
|
9
9
|
import { AgentsMdGenerator } from '../../adapters/agents-md-generator.js';
|
|
10
10
|
import { getDirname } from '../../utils/esm-helpers.js';
|
|
11
|
-
import {
|
|
11
|
+
import { LanguageManager, isLanguageSupported, getSupportedLanguages, getSystemPromptForLanguage } from '../../core/i18n/language-manager.js';
|
|
12
|
+
import { getLocaleManager } from '../../core/i18n/locale-manager.js';
|
|
12
13
|
const __dirname = getDirname(import.meta.url);
|
|
13
14
|
export async function initCommand(projectName, options = {}) {
|
|
14
|
-
|
|
15
|
+
// Validate and normalize language option
|
|
16
|
+
const language = options.language?.toLowerCase() || 'en';
|
|
17
|
+
// Validate language if provided
|
|
18
|
+
if (options.language && !isLanguageSupported(language)) {
|
|
19
|
+
const locale = getLocaleManager('en'); // Use English for error messages about invalid language
|
|
20
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.invalidLanguage', { language: options.language })}`));
|
|
21
|
+
console.error(chalk.yellow(`${locale.t('cli', 'init.errors.supportedLanguages', { languages: getSupportedLanguages().join(', ') })}\n`));
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
// Initialize LanguageManager and LocaleManager
|
|
25
|
+
const i18n = new LanguageManager({ defaultLanguage: language });
|
|
26
|
+
const locale = getLocaleManager(language);
|
|
27
|
+
// Display welcome message in user's language
|
|
28
|
+
console.log(chalk.blue.bold(`\n${locale.t('cli', 'init.welcome')}\n`));
|
|
15
29
|
let targetDir;
|
|
16
30
|
let finalProjectName;
|
|
17
31
|
let usedDotNotation = false;
|
|
@@ -22,7 +36,7 @@ export async function initCommand(projectName, options = {}) {
|
|
|
22
36
|
const dirName = path.basename(targetDir);
|
|
23
37
|
// Validate directory name is suitable for project name
|
|
24
38
|
if (!/^[a-z0-9-]+$/.test(dirName)) {
|
|
25
|
-
console.log(chalk.yellow(`\n
|
|
39
|
+
console.log(chalk.yellow(`\n${locale.t('cli', 'init.warnings.invalidDirName', { dirName })}`));
|
|
26
40
|
const suggestedName = dirName.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
27
41
|
const { name } = await inquirer.prompt([
|
|
28
42
|
{
|
|
@@ -46,7 +60,7 @@ export async function initCommand(projectName, options = {}) {
|
|
|
46
60
|
const allFiles = fs.readdirSync(targetDir);
|
|
47
61
|
const existingFiles = allFiles.filter(f => !f.startsWith('.')); // Ignore hidden files
|
|
48
62
|
if (existingFiles.length > 0) {
|
|
49
|
-
console.log(chalk.yellow(`\n
|
|
63
|
+
console.log(chalk.yellow(`\n${locale.t('cli', 'init.warnings.directoryNotEmpty', { count: existingFiles.length, plural: existingFiles.length === 1 ? '' : 's' })}`));
|
|
50
64
|
const { confirm } = await inquirer.prompt([
|
|
51
65
|
{
|
|
52
66
|
type: 'confirm',
|
|
@@ -56,7 +70,7 @@ export async function initCommand(projectName, options = {}) {
|
|
|
56
70
|
},
|
|
57
71
|
]);
|
|
58
72
|
if (!confirm) {
|
|
59
|
-
console.log(chalk.yellow('
|
|
73
|
+
console.log(chalk.yellow(locale.t('cli', 'init.errors.cancelled')));
|
|
60
74
|
process.exit(0);
|
|
61
75
|
}
|
|
62
76
|
}
|
|
@@ -71,7 +85,7 @@ export async function initCommand(projectName, options = {}) {
|
|
|
71
85
|
},
|
|
72
86
|
]);
|
|
73
87
|
if (!overwrite) {
|
|
74
|
-
console.log(chalk.yellow('
|
|
88
|
+
console.log(chalk.yellow(locale.t('cli', 'init.errors.cancelled')));
|
|
75
89
|
process.exit(0);
|
|
76
90
|
}
|
|
77
91
|
fs.removeSync(path.join(targetDir, '.specweave'));
|
|
@@ -112,7 +126,7 @@ export async function initCommand(projectName, options = {}) {
|
|
|
112
126
|
},
|
|
113
127
|
]);
|
|
114
128
|
if (!overwrite) {
|
|
115
|
-
console.log(chalk.yellow('
|
|
129
|
+
console.log(chalk.yellow(locale.t('cli', 'init.errors.cancelled')));
|
|
116
130
|
process.exit(0);
|
|
117
131
|
}
|
|
118
132
|
fs.emptyDirSync(targetDir);
|
|
@@ -121,86 +135,106 @@ export async function initCommand(projectName, options = {}) {
|
|
|
121
135
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
122
136
|
}
|
|
123
137
|
}
|
|
138
|
+
// 3. Check for nested .specweave/ (CRITICAL: prevent nested folders)
|
|
139
|
+
const parentSpecweave = detectNestedSpecweave(targetDir);
|
|
140
|
+
if (parentSpecweave) {
|
|
141
|
+
console.log('');
|
|
142
|
+
console.log(chalk.red.bold(locale.t('cli', 'init.errors.nestedNotSupported')));
|
|
143
|
+
console.log('');
|
|
144
|
+
console.log(chalk.yellow(` ${locale.t('cli', 'init.errors.parentFound')}`));
|
|
145
|
+
console.log(chalk.white(` ${parentSpecweave}`));
|
|
146
|
+
console.log('');
|
|
147
|
+
console.log(chalk.cyan(` ${locale.t('cli', 'init.info.nestedEnforcement')}`));
|
|
148
|
+
console.log(chalk.gray(` ${locale.t('cli', 'init.info.nestedBullet1')}`));
|
|
149
|
+
console.log(chalk.gray(` ${locale.t('cli', 'init.info.nestedBullet2')}`));
|
|
150
|
+
console.log(chalk.gray(` ${locale.t('cli', 'init.info.nestedBullet3')}`));
|
|
151
|
+
console.log('');
|
|
152
|
+
console.log(chalk.cyan(` ${locale.t('cli', 'init.info.nestedToFix')}`));
|
|
153
|
+
console.log(chalk.white(` ${locale.t('cli', 'init.nestedCdCommand', { path: parentSpecweave })}`));
|
|
154
|
+
console.log(chalk.white(` ${locale.t('cli', 'init.nestedIncCommand')}`));
|
|
155
|
+
console.log('');
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
124
158
|
const spinner = ora('Creating SpecWeave project...').start();
|
|
125
159
|
try {
|
|
126
|
-
//
|
|
160
|
+
// 4. Detect or select tool
|
|
127
161
|
const adapterLoader = new AdapterLoader();
|
|
128
162
|
let toolName;
|
|
129
163
|
if (options.adapter) {
|
|
130
|
-
// User explicitly chose a tool
|
|
164
|
+
// User explicitly chose a tool via --adapter flag
|
|
131
165
|
toolName = options.adapter;
|
|
132
166
|
spinner.text = `Using ${toolName}...`;
|
|
133
167
|
}
|
|
134
168
|
else {
|
|
135
|
-
// Auto-detect tool
|
|
169
|
+
// Auto-detect tool, then ASK USER to confirm or choose different
|
|
136
170
|
spinner.stop();
|
|
137
|
-
|
|
138
|
-
|
|
171
|
+
const detectedTool = await adapterLoader.detectTool();
|
|
172
|
+
console.log('');
|
|
173
|
+
console.log(chalk.cyan(`š ${locale.t('cli', 'init.toolDetection.header')}`));
|
|
174
|
+
console.log(chalk.gray(` ${locale.t('cli', 'init.toolDetection.detected', { tool: detectedTool })}`));
|
|
175
|
+
console.log('');
|
|
176
|
+
const { confirmTool } = await inquirer.prompt([
|
|
177
|
+
{
|
|
178
|
+
type: 'confirm',
|
|
179
|
+
name: 'confirmTool',
|
|
180
|
+
message: locale.t('cli', 'init.toolDetection.confirmPrompt', { tool: detectedTool }),
|
|
181
|
+
default: true
|
|
182
|
+
}
|
|
183
|
+
]);
|
|
184
|
+
if (confirmTool) {
|
|
185
|
+
toolName = detectedTool;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
// Let user choose from available tools
|
|
189
|
+
const { selectedTool } = await inquirer.prompt([
|
|
190
|
+
{
|
|
191
|
+
type: 'list',
|
|
192
|
+
name: 'selectedTool',
|
|
193
|
+
message: locale.t('cli', 'init.toolDetection.selectPrompt'),
|
|
194
|
+
choices: [
|
|
195
|
+
{ name: `${locale.t('cli', 'init.toolDetection.tools.claude')} (${locale.t('cli', 'init.toolDetection.recommended')})`, value: 'claude' },
|
|
196
|
+
{ name: locale.t('cli', 'init.toolDetection.tools.cursor'), value: 'cursor' },
|
|
197
|
+
{ name: locale.t('cli', 'init.toolDetection.tools.copilot'), value: 'copilot' },
|
|
198
|
+
{ name: locale.t('cli', 'init.toolDetection.tools.generic'), value: 'generic' }
|
|
199
|
+
]
|
|
200
|
+
}
|
|
201
|
+
]);
|
|
202
|
+
toolName = selectedTool;
|
|
203
|
+
}
|
|
204
|
+
spinner.start(`Using ${toolName}...`);
|
|
139
205
|
}
|
|
140
206
|
// 4. Create directory structure (same for all)
|
|
141
207
|
createDirectoryStructure(targetDir);
|
|
142
208
|
spinner.text = 'Directory structure created...';
|
|
143
|
-
// 5. Copy
|
|
144
|
-
const templatesDir = findSourceDir('templates');
|
|
145
|
-
await copyTemplates(templatesDir, targetDir, finalProjectName);
|
|
146
|
-
spinner.text = 'Base templates copied...';
|
|
147
|
-
// 6. Install based on tool
|
|
209
|
+
// 5. Copy plugin marketplace (for Claude Code auto-registration)
|
|
148
210
|
if (toolName === 'claude') {
|
|
149
|
-
// DEFAULT: Native Claude Code installation (no adapter needed!)
|
|
150
|
-
spinner.text = 'Installing Claude Code components...';
|
|
151
|
-
try {
|
|
152
|
-
copyCommands('', path.join(targetDir, '.claude/commands'));
|
|
153
|
-
spinner.text = 'Slash commands installed...';
|
|
154
|
-
}
|
|
155
|
-
catch (error) {
|
|
156
|
-
spinner.fail('Failed to copy commands');
|
|
157
|
-
console.error(chalk.red(`\nā Commands copy failed: ${error.message}`));
|
|
158
|
-
throw error;
|
|
159
|
-
}
|
|
160
|
-
try {
|
|
161
|
-
copyAgents('', path.join(targetDir, '.claude/agents'));
|
|
162
|
-
spinner.text = 'Agents installed...';
|
|
163
|
-
}
|
|
164
|
-
catch (error) {
|
|
165
|
-
spinner.fail('Failed to copy agents');
|
|
166
|
-
console.error(chalk.red(`\nā Agents copy failed: ${error.message}`));
|
|
167
|
-
throw error;
|
|
168
|
-
}
|
|
169
|
-
try {
|
|
170
|
-
copySkills('', path.join(targetDir, '.claude/skills'));
|
|
171
|
-
spinner.text = 'Skills installed...';
|
|
172
|
-
}
|
|
173
|
-
catch (error) {
|
|
174
|
-
spinner.fail('Failed to copy skills');
|
|
175
|
-
console.error(chalk.red(`\nā Skills copy failed: ${error.message}`));
|
|
176
|
-
throw error;
|
|
177
|
-
}
|
|
178
|
-
try {
|
|
179
|
-
copyHooks('', path.join(targetDir, '.claude/hooks'));
|
|
180
|
-
spinner.text = 'Hooks installed...';
|
|
181
|
-
}
|
|
182
|
-
catch (error) {
|
|
183
|
-
spinner.fail('Failed to copy hooks');
|
|
184
|
-
console.error(chalk.red(`\nā Hooks copy failed: ${error.message}`));
|
|
185
|
-
throw error;
|
|
186
|
-
}
|
|
187
211
|
try {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
212
|
+
const sourceMarketplace = findSourceDir('.claude-plugin');
|
|
213
|
+
const targetMarketplace = path.join(targetDir, '.claude-plugin');
|
|
214
|
+
if (fs.existsSync(sourceMarketplace)) {
|
|
215
|
+
fs.copySync(sourceMarketplace, targetMarketplace, {
|
|
216
|
+
overwrite: true,
|
|
217
|
+
errorOnExist: false
|
|
218
|
+
});
|
|
219
|
+
spinner.text = 'Plugin marketplace copied...';
|
|
220
|
+
}
|
|
196
221
|
}
|
|
197
222
|
catch (error) {
|
|
198
|
-
// Non-critical
|
|
199
|
-
console.warn(chalk.yellow(`\n
|
|
200
|
-
console.warn(chalk.yellow(' Skills will still work, but manual indexing may be needed.'));
|
|
223
|
+
// Non-critical - plugins can still be installed manually
|
|
224
|
+
console.warn(chalk.yellow(`\n${locale.t('cli', 'init.warnings.marketplaceCopyFailed')}`));
|
|
201
225
|
}
|
|
202
|
-
|
|
203
|
-
|
|
226
|
+
}
|
|
227
|
+
// 6. Copy base templates (config, README, CLAUDE.md - same for all)
|
|
228
|
+
const templatesDir = findSourceDir('templates');
|
|
229
|
+
await copyTemplates(templatesDir, targetDir, finalProjectName, language);
|
|
230
|
+
spinner.text = 'Base templates copied...';
|
|
231
|
+
// 6. Install based on tool
|
|
232
|
+
if (toolName === 'claude') {
|
|
233
|
+
// DEFAULT: Native Claude Code plugins (installed globally via /plugin install)
|
|
234
|
+
// No per-project copying needed - plugins work across all projects!
|
|
235
|
+
spinner.text = 'Configuring for Claude Code...';
|
|
236
|
+
console.log(`\n${locale.t('cli', 'init.claudeNativeComplete')}`);
|
|
237
|
+
console.log(` ${locale.t('cli', 'init.claudeNativeBenefits')}`);
|
|
204
238
|
}
|
|
205
239
|
else {
|
|
206
240
|
// Use adapter for non-Claude tools
|
|
@@ -216,25 +250,59 @@ export async function initCommand(projectName, options = {}) {
|
|
|
216
250
|
techStack: options.techStack ? { language: options.techStack } : undefined,
|
|
217
251
|
docsApproach: 'incremental'
|
|
218
252
|
});
|
|
253
|
+
// 7. Install core plugin for non-Claude adapters
|
|
254
|
+
// CRITICAL: Cursor/Copilot/Generic need plugin files in project!
|
|
255
|
+
// Claude uses plugin system (global), but others need local files for AGENTS.md/instructions.md
|
|
256
|
+
try {
|
|
257
|
+
spinner.start('Installing SpecWeave core plugin...');
|
|
258
|
+
// Load core plugin from plugins/specweave/
|
|
259
|
+
const corePluginPath = findSourceDir('plugins/specweave');
|
|
260
|
+
const { PluginLoader } = await import('../../core/plugin-loader.js');
|
|
261
|
+
const loader = new PluginLoader();
|
|
262
|
+
const corePlugin = await loader.loadFromDirectory(corePluginPath);
|
|
263
|
+
// Compile for adapter (Cursor ā AGENTS.md, Copilot ā instructions.md, etc.)
|
|
264
|
+
if (adapter.supportsPlugins()) {
|
|
265
|
+
await adapter.compilePlugin(corePlugin);
|
|
266
|
+
spinner.succeed('SpecWeave core plugin installed');
|
|
267
|
+
console.log(chalk.green(' ā Skills, agents, commands added to project'));
|
|
268
|
+
console.log(chalk.gray(` ā ${corePlugin.skills.length} skills, ${corePlugin.agents.length} agents, ${corePlugin.commands.length} commands`));
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
spinner.warn('Adapter does not support plugins');
|
|
272
|
+
console.log(chalk.yellow(' ā Core functionality may be limited'));
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
spinner.warn('Could not install core plugin');
|
|
277
|
+
console.log(chalk.yellow(` ${error instanceof Error ? error.message : error}`));
|
|
278
|
+
console.log(chalk.gray(' ā You can manually reference plugin files if needed'));
|
|
279
|
+
}
|
|
219
280
|
}
|
|
220
281
|
// 9. Initialize git (skip if .git already exists)
|
|
221
282
|
const gitDir = path.join(targetDir, '.git');
|
|
222
283
|
if (!fs.existsSync(gitDir)) {
|
|
223
|
-
|
|
224
|
-
|
|
284
|
+
// Use secure command execution for git commands
|
|
285
|
+
const gitInitResult = execFileNoThrowSync('git', ['init'], { cwd: targetDir });
|
|
286
|
+
if (gitInitResult.success) {
|
|
225
287
|
spinner.text = 'Git repository initialized...';
|
|
226
288
|
}
|
|
227
|
-
|
|
289
|
+
else {
|
|
228
290
|
spinner.warn('Git initialization skipped (git not found)');
|
|
229
291
|
}
|
|
230
|
-
// 10. Create initial commit
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
292
|
+
// 10. Create initial commit (if git init succeeded)
|
|
293
|
+
if (gitInitResult.success) {
|
|
294
|
+
const gitAddResult = execFileNoThrowSync('git', ['add', '.'], { cwd: targetDir });
|
|
295
|
+
if (gitAddResult.success) {
|
|
296
|
+
const gitCommitResult = execFileNoThrowSync('git', [
|
|
297
|
+
'commit',
|
|
298
|
+
'-m',
|
|
299
|
+
'Initial commit with SpecWeave'
|
|
300
|
+
], { cwd: targetDir });
|
|
301
|
+
if (gitCommitResult.success) {
|
|
302
|
+
spinner.text = 'Initial commit created...';
|
|
303
|
+
}
|
|
304
|
+
// Git commit might fail if no user configured - that's ok, no need to warn
|
|
305
|
+
}
|
|
238
306
|
}
|
|
239
307
|
}
|
|
240
308
|
else {
|
|
@@ -252,7 +320,7 @@ export async function initCommand(projectName, options = {}) {
|
|
|
252
320
|
const suggestedPlugins = detectionResults.map(r => r.pluginName);
|
|
253
321
|
pluginSpinner.succeed(`Detected ${suggestedPlugins.length} suggested plugins`);
|
|
254
322
|
if (suggestedPlugins.length > 0) {
|
|
255
|
-
console.log(chalk.cyan('
|
|
323
|
+
console.log(chalk.cyan(`\n${locale.t('cli', 'init.info.suggestedPlugins')}`));
|
|
256
324
|
for (const pluginName of suggestedPlugins) {
|
|
257
325
|
console.log(` ⢠${chalk.white(pluginName)}`);
|
|
258
326
|
}
|
|
@@ -286,7 +354,7 @@ export async function initCommand(projectName, options = {}) {
|
|
|
286
354
|
}
|
|
287
355
|
catch (error) {
|
|
288
356
|
pluginSpinner.warn('Plugin detection skipped');
|
|
289
|
-
console.log(chalk.gray(`
|
|
357
|
+
console.log(chalk.gray(` ${locale.t('cli', 'init.pluginEnableLater')}`));
|
|
290
358
|
}
|
|
291
359
|
// 12. Show tool-specific next steps
|
|
292
360
|
if (toolName !== 'claude') {
|
|
@@ -300,11 +368,113 @@ export async function initCommand(projectName, options = {}) {
|
|
|
300
368
|
});
|
|
301
369
|
}
|
|
302
370
|
}
|
|
303
|
-
|
|
371
|
+
// 13. Create config.json with language setting
|
|
372
|
+
createConfigFile(targetDir, finalProjectName, toolName, language);
|
|
373
|
+
// 14. Setup Claude Code plugin auto-registration (if Claude detected)
|
|
374
|
+
let autoInstallSucceeded = false;
|
|
375
|
+
if (toolName === 'claude') {
|
|
376
|
+
try {
|
|
377
|
+
setupClaudePluginAutoRegistration(targetDir, language);
|
|
378
|
+
}
|
|
379
|
+
catch (error) {
|
|
380
|
+
// Non-critical - show manual instructions in next steps
|
|
381
|
+
console.warn(chalk.yellow(`\n${locale.t('cli', 'init.warnings.pluginAutoSetupFailed')}`));
|
|
382
|
+
}
|
|
383
|
+
// 15. AUTO-INSTALL CORE PLUGIN via Claude CLI (Secure + Cross-Platform)
|
|
384
|
+
// Pre-flight check: Is Claude CLI available?
|
|
385
|
+
if (!isCommandAvailableSync('claude')) {
|
|
386
|
+
// Claude CLI NOT found ā explain clearly with actionable options
|
|
387
|
+
spinner.warn('Claude CLI not found in PATH');
|
|
388
|
+
console.log('');
|
|
389
|
+
console.log(chalk.yellow.bold('ā ļø Claude Code CLI Required'));
|
|
390
|
+
console.log('');
|
|
391
|
+
console.log(chalk.white('SpecWeave needs Claude Code installed to auto-configure plugins.'));
|
|
392
|
+
console.log('');
|
|
393
|
+
console.log(chalk.cyan('Options:'));
|
|
394
|
+
console.log('');
|
|
395
|
+
console.log(chalk.white('1ļøā£ Install Claude Code (Recommended):'));
|
|
396
|
+
console.log(chalk.gray(' ā https://claude.com/code'));
|
|
397
|
+
console.log(chalk.gray(' ā Once installed, re-run: specweave init'));
|
|
398
|
+
console.log('');
|
|
399
|
+
console.log(chalk.white('2ļøā£ Manual Plugin Installation:'));
|
|
400
|
+
console.log(chalk.gray(' ā Open project in Claude Code'));
|
|
401
|
+
console.log(chalk.gray(' ā Run: /plugin install specweave@specweave'));
|
|
402
|
+
console.log('');
|
|
403
|
+
console.log(chalk.white('3ļøā£ Use Different Adapter:'));
|
|
404
|
+
console.log(chalk.gray(' ā specweave init --adapter cursor'));
|
|
405
|
+
console.log(chalk.gray(' ā Works without Claude CLI (uses AGENTS.md)'));
|
|
406
|
+
console.log('');
|
|
407
|
+
autoInstallSucceeded = false;
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
// Claude CLI available ā attempt secure auto-install
|
|
411
|
+
try {
|
|
412
|
+
spinner.start('Installing SpecWeave core plugin...');
|
|
413
|
+
// Step 1: Add marketplace (idempotent - safe if already exists)
|
|
414
|
+
const projectRoot = targetDir;
|
|
415
|
+
const marketplaceJsonPath = path.join(projectRoot, '.claude-plugin', 'marketplace.json');
|
|
416
|
+
if (fs.existsSync(marketplaceJsonPath)) {
|
|
417
|
+
// ā
SECURE: Arguments in array (no shell interpolation, no injection risk)
|
|
418
|
+
const marketplaceResult = execFileNoThrowSync('claude', [
|
|
419
|
+
'plugin',
|
|
420
|
+
'marketplace',
|
|
421
|
+
'add',
|
|
422
|
+
projectRoot // ā
Safely escaped automatically
|
|
423
|
+
]);
|
|
424
|
+
// Marketplace add can fail if already exists - that's OK
|
|
425
|
+
if (!marketplaceResult.success && process.env.DEBUG) {
|
|
426
|
+
console.log(chalk.gray(` Marketplace note: ${marketplaceResult.stderr}`));
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
// Step 2: Install core plugin
|
|
430
|
+
// ā
SECURE: No string interpolation, no shell, cross-platform
|
|
431
|
+
const installResult = execFileNoThrowSync('claude', [
|
|
432
|
+
'plugin',
|
|
433
|
+
'install',
|
|
434
|
+
'specweave@specweave'
|
|
435
|
+
]);
|
|
436
|
+
if (installResult.success) {
|
|
437
|
+
autoInstallSucceeded = true;
|
|
438
|
+
spinner.succeed('SpecWeave core plugin installed automatically!');
|
|
439
|
+
console.log(chalk.green(' ā Slash commands ready: /specweave:inc'));
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
throw new Error(installResult.stderr || installResult.stdout || 'Installation failed');
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
catch (error) {
|
|
446
|
+
// Installation failed - provide helpful diagnostics
|
|
447
|
+
spinner.warn('Could not auto-install core plugin');
|
|
448
|
+
console.log('');
|
|
449
|
+
// Diagnose error and provide actionable hints
|
|
450
|
+
if (error.message.includes('not found') || error.message.includes('ENOENT')) {
|
|
451
|
+
console.log(chalk.yellow(' Reason: Claude CLI found but command failed'));
|
|
452
|
+
console.log(chalk.gray(' ā Try manually: claude plugin install specweave@specweave'));
|
|
453
|
+
}
|
|
454
|
+
else if (error.message.includes('EACCES') || error.message.includes('permission')) {
|
|
455
|
+
console.log(chalk.yellow(' Reason: Permission denied'));
|
|
456
|
+
console.log(chalk.gray(' ā Check file permissions or run with appropriate access'));
|
|
457
|
+
}
|
|
458
|
+
else if (error.message.includes('ECONNREFUSED') || error.message.includes('network')) {
|
|
459
|
+
console.log(chalk.yellow(' Reason: Network error'));
|
|
460
|
+
console.log(chalk.gray(' ā Check internet connection and try again'));
|
|
461
|
+
}
|
|
462
|
+
else if (process.env.DEBUG) {
|
|
463
|
+
console.log(chalk.gray(` Error: ${error.message}`));
|
|
464
|
+
}
|
|
465
|
+
console.log('');
|
|
466
|
+
console.log(chalk.cyan('š¦ Manual installation:'));
|
|
467
|
+
console.log(chalk.white(' /plugin install specweave@specweave'));
|
|
468
|
+
console.log('');
|
|
469
|
+
autoInstallSucceeded = false;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
showNextSteps(finalProjectName, toolName, language, usedDotNotation, toolName === 'claude' ? autoInstallSucceeded : undefined);
|
|
304
474
|
}
|
|
305
475
|
catch (error) {
|
|
306
476
|
spinner.fail('Failed to create project');
|
|
307
|
-
console.error(chalk.red('
|
|
477
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.genericError')}`), error);
|
|
308
478
|
process.exit(1);
|
|
309
479
|
}
|
|
310
480
|
}
|
|
@@ -329,18 +499,19 @@ function createDirectoryStructure(targetDir) {
|
|
|
329
499
|
fs.mkdirSync(path.join(targetDir, dir), { recursive: true });
|
|
330
500
|
});
|
|
331
501
|
}
|
|
332
|
-
async function copyTemplates(templatesDir, targetDir, projectName) {
|
|
502
|
+
async function copyTemplates(templatesDir, targetDir, projectName, language = 'en') {
|
|
503
|
+
const locale = getLocaleManager(language);
|
|
333
504
|
// Verify templates directory exists
|
|
334
505
|
if (!fs.existsSync(templatesDir)) {
|
|
335
|
-
console.error(chalk.red(`\n
|
|
506
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.templatesNotFound', { path: templatesDir })}`));
|
|
336
507
|
const packageRoot = findPackageRoot(__dirname);
|
|
337
508
|
if (packageRoot) {
|
|
338
|
-
console.error(chalk.red(`
|
|
339
|
-
console.error(chalk.red(`
|
|
509
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.packageRoot', { root: packageRoot })}`));
|
|
510
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.tryingAlternate')}`));
|
|
340
511
|
// Try src/templates as fallback
|
|
341
512
|
const altPath = path.join(packageRoot, 'src', 'templates');
|
|
342
513
|
if (fs.existsSync(altPath)) {
|
|
343
|
-
console.error(chalk.yellow(`
|
|
514
|
+
console.error(chalk.yellow(` ${locale.t('cli', 'init.errors.foundTemplatesAt', { path: altPath })}`));
|
|
344
515
|
templatesDir = altPath;
|
|
345
516
|
}
|
|
346
517
|
else {
|
|
@@ -391,6 +562,33 @@ async function copyTemplates(templatesDir, targetDir, projectName) {
|
|
|
391
562
|
fs.copyFileSync(gitignoreTemplate, path.join(targetDir, '.gitignore'));
|
|
392
563
|
}
|
|
393
564
|
}
|
|
565
|
+
/**
|
|
566
|
+
* Detect if a parent directory contains a .specweave/ folder
|
|
567
|
+
* SpecWeave ONLY supports root-level .specweave/ folders
|
|
568
|
+
* Nested .specweave/ folders are NOT supported
|
|
569
|
+
*
|
|
570
|
+
* @param targetDir - Directory where user wants to initialize
|
|
571
|
+
* @returns Path to parent .specweave/ folder, or null if none found
|
|
572
|
+
*/
|
|
573
|
+
function detectNestedSpecweave(targetDir) {
|
|
574
|
+
// Start from parent of target directory
|
|
575
|
+
let currentDir = path.dirname(path.resolve(targetDir));
|
|
576
|
+
const root = path.parse(currentDir).root;
|
|
577
|
+
// Walk up the directory tree
|
|
578
|
+
while (currentDir !== root) {
|
|
579
|
+
const specweavePath = path.join(currentDir, '.specweave');
|
|
580
|
+
// Check if .specweave/ exists at this level
|
|
581
|
+
if (fs.existsSync(specweavePath)) {
|
|
582
|
+
return currentDir; // Found parent .specweave/
|
|
583
|
+
}
|
|
584
|
+
// Move up one level
|
|
585
|
+
const parentDir = path.dirname(currentDir);
|
|
586
|
+
if (parentDir === currentDir)
|
|
587
|
+
break; // Reached root
|
|
588
|
+
currentDir = parentDir;
|
|
589
|
+
}
|
|
590
|
+
return null; // No parent .specweave/ found
|
|
591
|
+
}
|
|
394
592
|
/**
|
|
395
593
|
* Find the package root by walking up the directory tree looking for package.json
|
|
396
594
|
* This works reliably on all platforms including Windows with UNC paths
|
|
@@ -463,63 +661,73 @@ function findSourceDir(relativePath) {
|
|
|
463
661
|
// If nothing found, return the first path and let the caller handle the error
|
|
464
662
|
return possiblePaths[0];
|
|
465
663
|
}
|
|
466
|
-
function copyCommands(commandsDir, targetCommandsDir) {
|
|
467
|
-
const
|
|
664
|
+
function copyCommands(commandsDir, targetCommandsDir, language) {
|
|
665
|
+
const locale = getLocaleManager(language);
|
|
666
|
+
// v0.4.0+: Commands moved to plugins/specweave/commands/
|
|
667
|
+
const sourceDir = findSourceDir('plugins/specweave/commands');
|
|
468
668
|
if (!fs.existsSync(sourceDir)) {
|
|
469
|
-
console.error(chalk.red(`\n
|
|
470
|
-
console.error(chalk.red(`
|
|
471
|
-
console.error(chalk.red(`
|
|
669
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.sourceNotFound', { type: 'commands' })}`));
|
|
670
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.expectedAt', { path: sourceDir })}`));
|
|
671
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.dirname', { path: __dirname })}`));
|
|
472
672
|
const packageRoot = findPackageRoot(__dirname);
|
|
473
673
|
if (packageRoot) {
|
|
474
|
-
console.error(chalk.red(`
|
|
674
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.packageRoot', { root: packageRoot })}`));
|
|
475
675
|
}
|
|
476
676
|
else {
|
|
477
|
-
console.error(chalk.red(`
|
|
677
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.couldNotFindRoot')}`));
|
|
478
678
|
}
|
|
479
679
|
throw new Error('Failed to locate source commands directory. This may be a Windows path resolution issue.');
|
|
480
680
|
}
|
|
481
681
|
// Validate source directory contains files
|
|
482
682
|
const sourceFiles = fs.readdirSync(sourceDir).filter(f => f.endsWith('.md'));
|
|
483
683
|
if (sourceFiles.length === 0) {
|
|
484
|
-
console.error(chalk.red(`\n
|
|
485
|
-
console.error(chalk.red(`
|
|
486
|
-
console.error(chalk.red(`
|
|
684
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.sourceEmpty', { type: 'commands' })}`));
|
|
685
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.directory', { path: sourceDir })}`));
|
|
686
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.installationIssue')}`));
|
|
487
687
|
throw new Error('Source commands directory exists but contains no .md files');
|
|
488
688
|
}
|
|
489
689
|
try {
|
|
490
690
|
// Ensure target directory exists
|
|
491
691
|
fs.ensureDirSync(targetCommandsDir);
|
|
492
|
-
// Copy
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
692
|
+
// Copy each command file and inject system prompts if needed
|
|
693
|
+
for (const file of sourceFiles) {
|
|
694
|
+
const sourcePath = path.join(sourceDir, file);
|
|
695
|
+
const targetPath = path.join(targetCommandsDir, file);
|
|
696
|
+
// Read, potentially inject, and write
|
|
697
|
+
const content = fs.readFileSync(sourcePath, 'utf-8');
|
|
698
|
+
const modifiedContent = language !== 'en'
|
|
699
|
+
? injectSystemPromptForInit(content, language)
|
|
700
|
+
: content;
|
|
701
|
+
fs.writeFileSync(targetPath, modifiedContent, 'utf-8');
|
|
702
|
+
}
|
|
497
703
|
// Validate files were copied
|
|
498
704
|
const copiedFiles = fs.readdirSync(targetCommandsDir).filter(f => f.endsWith('.md'));
|
|
499
705
|
if (copiedFiles.length === 0) {
|
|
500
706
|
throw new Error(`Copy completed but no files found in target directory: ${targetCommandsDir}`);
|
|
501
707
|
}
|
|
502
|
-
console.log(chalk.gray(`
|
|
708
|
+
console.log(chalk.gray(` ${locale.t('cli', 'init.info.copiedFiles', { count: copiedFiles.length })}`));
|
|
503
709
|
}
|
|
504
710
|
catch (error) {
|
|
505
|
-
console.error(chalk.red(`\n
|
|
506
|
-
console.error(chalk.red(`
|
|
507
|
-
console.error(chalk.red(`
|
|
711
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.errorCopying', { type: 'commands', error: error.message })}`));
|
|
712
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.source', { path: sourceDir })}`));
|
|
713
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.target', { path: targetCommandsDir })}`));
|
|
508
714
|
throw error;
|
|
509
715
|
}
|
|
510
716
|
}
|
|
511
|
-
function copyAgents(agentsDir, targetAgentsDir) {
|
|
512
|
-
const
|
|
717
|
+
function copyAgents(agentsDir, targetAgentsDir, language) {
|
|
718
|
+
const locale = getLocaleManager(language);
|
|
719
|
+
// v0.4.0+: Agents moved to plugins/specweave/agents/
|
|
720
|
+
const sourceDir = findSourceDir('plugins/specweave/agents');
|
|
513
721
|
if (!fs.existsSync(sourceDir)) {
|
|
514
|
-
console.error(chalk.red(`\n
|
|
515
|
-
console.error(chalk.red(`
|
|
516
|
-
console.error(chalk.red(`
|
|
722
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.sourceNotFound', { type: 'agents' })}`));
|
|
723
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.expectedAt', { path: sourceDir })}`));
|
|
724
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.dirname', { path: __dirname })}`));
|
|
517
725
|
const packageRoot = findPackageRoot(__dirname);
|
|
518
726
|
if (packageRoot) {
|
|
519
|
-
console.error(chalk.red(`
|
|
727
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.packageRoot', { root: packageRoot })}`));
|
|
520
728
|
}
|
|
521
729
|
else {
|
|
522
|
-
console.error(chalk.red(`
|
|
730
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.couldNotFindRoot')}`));
|
|
523
731
|
}
|
|
524
732
|
throw new Error('Failed to locate source agents directory. This may be a Windows path resolution issue.');
|
|
525
733
|
}
|
|
@@ -527,46 +735,82 @@ function copyAgents(agentsDir, targetAgentsDir) {
|
|
|
527
735
|
const agentDirs = fs.readdirSync(sourceDir, { withFileTypes: true })
|
|
528
736
|
.filter(dirent => dirent.isDirectory());
|
|
529
737
|
if (agentDirs.length === 0) {
|
|
530
|
-
console.error(chalk.red(`\n
|
|
531
|
-
console.error(chalk.red(`
|
|
532
|
-
console.error(chalk.red(`
|
|
738
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.sourceEmpty', { type: 'agents' })}`));
|
|
739
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.directory', { path: sourceDir })}`));
|
|
740
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.installationIssue')}`));
|
|
533
741
|
throw new Error('Source agents directory exists but contains no agent subdirectories');
|
|
534
742
|
}
|
|
535
743
|
try {
|
|
536
744
|
// Ensure target directory exists
|
|
537
745
|
fs.ensureDirSync(targetAgentsDir);
|
|
538
|
-
// Copy
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
746
|
+
// Copy each agent directory and inject system prompts if needed
|
|
747
|
+
for (const agentDir of agentDirs) {
|
|
748
|
+
const sourcePath = path.join(sourceDir, agentDir.name);
|
|
749
|
+
const targetPath = path.join(targetAgentsDir, agentDir.name);
|
|
750
|
+
// Copy entire agent directory first
|
|
751
|
+
fs.copySync(sourcePath, targetPath, {
|
|
752
|
+
overwrite: true,
|
|
753
|
+
errorOnExist: false
|
|
754
|
+
});
|
|
755
|
+
// Then inject system prompt into AGENT.md if language !== 'en'
|
|
756
|
+
if (language !== 'en') {
|
|
757
|
+
const agentMdPath = path.join(targetPath, 'AGENT.md');
|
|
758
|
+
if (fs.existsSync(agentMdPath)) {
|
|
759
|
+
const content = fs.readFileSync(agentMdPath, 'utf-8');
|
|
760
|
+
const modifiedContent = injectSystemPromptForInit(content, language);
|
|
761
|
+
fs.writeFileSync(agentMdPath, modifiedContent, 'utf-8');
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
543
765
|
// Validate subdirectories were copied
|
|
544
766
|
const copiedDirs = fs.readdirSync(targetAgentsDir, { withFileTypes: true })
|
|
545
767
|
.filter(dirent => dirent.isDirectory());
|
|
546
768
|
if (copiedDirs.length === 0) {
|
|
547
769
|
throw new Error(`Copy completed but no agent directories found in target: ${targetAgentsDir}`);
|
|
548
770
|
}
|
|
549
|
-
console.log(chalk.gray(`
|
|
771
|
+
console.log(chalk.gray(` ${locale.t('cli', 'init.info.copiedAgents', { count: copiedDirs.length })}`));
|
|
550
772
|
}
|
|
551
773
|
catch (error) {
|
|
552
|
-
console.error(chalk.red(`\n
|
|
553
|
-
console.error(chalk.red(`
|
|
554
|
-
console.error(chalk.red(`
|
|
774
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.errorCopying', { type: 'agents', error: error.message })}`));
|
|
775
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.source', { path: sourceDir })}`));
|
|
776
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.target', { path: targetAgentsDir })}`));
|
|
555
777
|
throw error;
|
|
556
778
|
}
|
|
557
779
|
}
|
|
558
|
-
|
|
559
|
-
|
|
780
|
+
/**
|
|
781
|
+
* Inject system prompt for non-English languages
|
|
782
|
+
*/
|
|
783
|
+
function injectSystemPromptForInit(content, language) {
|
|
784
|
+
if (language === 'en') {
|
|
785
|
+
return content; // No changes for English
|
|
786
|
+
}
|
|
787
|
+
const systemPrompt = getSystemPromptForLanguage(language);
|
|
788
|
+
// Inject after YAML frontmatter if present
|
|
789
|
+
if (content.startsWith('---')) {
|
|
790
|
+
const endOfFrontmatter = content.indexOf('---', 3);
|
|
791
|
+
if (endOfFrontmatter !== -1) {
|
|
792
|
+
const frontmatter = content.substring(0, endOfFrontmatter + 3);
|
|
793
|
+
const body = content.substring(endOfFrontmatter + 3);
|
|
794
|
+
return `${frontmatter}\n\n${systemPrompt}\n${body}`;
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
// No frontmatter - inject at the top
|
|
798
|
+
return `${systemPrompt}\n\n${content}`;
|
|
799
|
+
}
|
|
800
|
+
function copySkills(skillsDir, targetSkillsDir, language) {
|
|
801
|
+
const locale = getLocaleManager(language);
|
|
802
|
+
// v0.4.0+: Skills moved to plugins/specweave/skills/
|
|
803
|
+
const sourceDir = findSourceDir('plugins/specweave/skills');
|
|
560
804
|
if (!fs.existsSync(sourceDir)) {
|
|
561
|
-
console.error(chalk.red(`\n
|
|
562
|
-
console.error(chalk.red(`
|
|
563
|
-
console.error(chalk.red(`
|
|
805
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.sourceNotFound', { type: 'skills' })}`));
|
|
806
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.expectedAt', { path: sourceDir })}`));
|
|
807
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.dirname', { path: __dirname })}`));
|
|
564
808
|
const packageRoot = findPackageRoot(__dirname);
|
|
565
809
|
if (packageRoot) {
|
|
566
|
-
console.error(chalk.red(`
|
|
810
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.packageRoot', { root: packageRoot })}`));
|
|
567
811
|
}
|
|
568
812
|
else {
|
|
569
|
-
console.error(chalk.red(`
|
|
813
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.couldNotFindRoot')}`));
|
|
570
814
|
}
|
|
571
815
|
throw new Error('Failed to locate source skills directory. This may be a Windows path resolution issue.');
|
|
572
816
|
}
|
|
@@ -574,55 +818,71 @@ function copySkills(skillsDir, targetSkillsDir) {
|
|
|
574
818
|
const skillDirs = fs.readdirSync(sourceDir, { withFileTypes: true })
|
|
575
819
|
.filter(dirent => dirent.isDirectory());
|
|
576
820
|
if (skillDirs.length === 0) {
|
|
577
|
-
console.error(chalk.red(`\n
|
|
578
|
-
console.error(chalk.red(`
|
|
579
|
-
console.error(chalk.red(`
|
|
821
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.sourceEmpty', { type: 'skills' })}`));
|
|
822
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.directory', { path: sourceDir })}`));
|
|
823
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.installationIssue')}`));
|
|
580
824
|
throw new Error('Source skills directory exists but contains no skill subdirectories');
|
|
581
825
|
}
|
|
582
826
|
try {
|
|
583
827
|
// Ensure target directory exists
|
|
584
828
|
fs.ensureDirSync(targetSkillsDir);
|
|
585
|
-
// Copy
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
829
|
+
// Copy each skill directory and inject system prompts if needed
|
|
830
|
+
for (const skillDir of skillDirs) {
|
|
831
|
+
const sourcePath = path.join(sourceDir, skillDir.name);
|
|
832
|
+
const targetPath = path.join(targetSkillsDir, skillDir.name);
|
|
833
|
+
// Copy entire skill directory first
|
|
834
|
+
fs.copySync(sourcePath, targetPath, {
|
|
835
|
+
overwrite: true,
|
|
836
|
+
errorOnExist: false
|
|
837
|
+
});
|
|
838
|
+
// Then inject system prompt into SKILL.md if language !== 'en'
|
|
839
|
+
if (language !== 'en') {
|
|
840
|
+
const skillMdPath = path.join(targetPath, 'SKILL.md');
|
|
841
|
+
if (fs.existsSync(skillMdPath)) {
|
|
842
|
+
const content = fs.readFileSync(skillMdPath, 'utf-8');
|
|
843
|
+
const modifiedContent = injectSystemPromptForInit(content, language);
|
|
844
|
+
fs.writeFileSync(skillMdPath, modifiedContent, 'utf-8');
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
}
|
|
590
848
|
// Validate subdirectories were copied
|
|
591
849
|
const copiedDirs = fs.readdirSync(targetSkillsDir, { withFileTypes: true })
|
|
592
850
|
.filter(dirent => dirent.isDirectory());
|
|
593
851
|
if (copiedDirs.length === 0) {
|
|
594
852
|
throw new Error(`Copy completed but no skill directories found in target: ${targetSkillsDir}`);
|
|
595
853
|
}
|
|
596
|
-
console.log(chalk.gray(`
|
|
854
|
+
console.log(chalk.gray(` ${locale.t('cli', 'init.info.copiedSkills', { count: copiedDirs.length })}`));
|
|
597
855
|
}
|
|
598
856
|
catch (error) {
|
|
599
|
-
console.error(chalk.red(`\n
|
|
600
|
-
console.error(chalk.red(`
|
|
601
|
-
console.error(chalk.red(`
|
|
857
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.errorCopying', { type: 'skills', error: error.message })}`));
|
|
858
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.source', { path: sourceDir })}`));
|
|
859
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.target', { path: targetSkillsDir })}`));
|
|
602
860
|
throw error;
|
|
603
861
|
}
|
|
604
862
|
}
|
|
605
|
-
function copyHooks(hooksDir, targetHooksDir) {
|
|
606
|
-
const
|
|
863
|
+
function copyHooks(hooksDir, targetHooksDir, language = 'en') {
|
|
864
|
+
const locale = getLocaleManager(language);
|
|
865
|
+
// v0.4.0+: Hooks moved to plugins/specweave/hooks/
|
|
866
|
+
const sourceDir = findSourceDir('plugins/specweave/hooks');
|
|
607
867
|
if (!fs.existsSync(sourceDir)) {
|
|
608
|
-
console.error(chalk.red(`\n
|
|
609
|
-
console.error(chalk.red(`
|
|
610
|
-
console.error(chalk.red(`
|
|
868
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.sourceNotFound', { type: 'hooks' })}`));
|
|
869
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.expectedAt', { path: sourceDir })}`));
|
|
870
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.dirname', { path: __dirname })}`));
|
|
611
871
|
const packageRoot = findPackageRoot(__dirname);
|
|
612
872
|
if (packageRoot) {
|
|
613
|
-
console.error(chalk.red(`
|
|
873
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.packageRoot', { root: packageRoot })}`));
|
|
614
874
|
}
|
|
615
875
|
else {
|
|
616
|
-
console.error(chalk.red(`
|
|
876
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.couldNotFindRoot')}`));
|
|
617
877
|
}
|
|
618
878
|
throw new Error('Failed to locate source hooks directory. This may be a Windows path resolution issue.');
|
|
619
879
|
}
|
|
620
880
|
// Validate source directory contains hook files
|
|
621
881
|
const hookFiles = fs.readdirSync(sourceDir).filter(f => f.endsWith('.sh') || f === 'README.md');
|
|
622
882
|
if (hookFiles.length === 0) {
|
|
623
|
-
console.error(chalk.red(`\n
|
|
624
|
-
console.error(chalk.red(`
|
|
625
|
-
console.error(chalk.red(`
|
|
883
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.sourceEmpty', { type: 'hooks' })}`));
|
|
884
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.directory', { path: sourceDir })}`));
|
|
885
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.installationIssue')}`));
|
|
626
886
|
throw new Error('Source hooks directory exists but contains no hook files');
|
|
627
887
|
}
|
|
628
888
|
try {
|
|
@@ -638,65 +898,141 @@ function copyHooks(hooksDir, targetHooksDir) {
|
|
|
638
898
|
if (copiedFiles.length === 0) {
|
|
639
899
|
throw new Error(`Copy completed but no hook files found in target: ${targetHooksDir}`);
|
|
640
900
|
}
|
|
641
|
-
console.log(chalk.gray(`
|
|
901
|
+
console.log(chalk.gray(` ${locale.t('cli', 'init.info.copiedHooks', { count: copiedFiles.length })}`));
|
|
642
902
|
}
|
|
643
903
|
catch (error) {
|
|
644
|
-
console.error(chalk.red(`\n
|
|
645
|
-
console.error(chalk.red(`
|
|
646
|
-
console.error(chalk.red(`
|
|
904
|
+
console.error(chalk.red(`\n${locale.t('cli', 'init.errors.errorCopying', { type: 'hooks', error: error.message })}`));
|
|
905
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.source', { path: sourceDir })}`));
|
|
906
|
+
console.error(chalk.red(` ${locale.t('cli', 'init.errors.target', { path: targetHooksDir })}`));
|
|
647
907
|
throw error;
|
|
648
908
|
}
|
|
649
909
|
}
|
|
650
|
-
|
|
910
|
+
/**
|
|
911
|
+
* Create .specweave/config.json with project settings
|
|
912
|
+
*/
|
|
913
|
+
function createConfigFile(targetDir, projectName, adapter, language) {
|
|
914
|
+
const configPath = path.join(targetDir, '.specweave', 'config.json');
|
|
915
|
+
const config = {
|
|
916
|
+
project: {
|
|
917
|
+
name: projectName,
|
|
918
|
+
version: '0.1.0',
|
|
919
|
+
},
|
|
920
|
+
adapters: {
|
|
921
|
+
default: adapter,
|
|
922
|
+
},
|
|
923
|
+
// Only include language if non-English
|
|
924
|
+
...(language !== 'en' && {
|
|
925
|
+
language,
|
|
926
|
+
translation: {
|
|
927
|
+
method: 'in-session',
|
|
928
|
+
autoTranslateLivingDocs: false,
|
|
929
|
+
keepFrameworkTerms: true,
|
|
930
|
+
keepTechnicalTerms: true,
|
|
931
|
+
translateCodeComments: true,
|
|
932
|
+
translateVariableNames: false,
|
|
933
|
+
},
|
|
934
|
+
}),
|
|
935
|
+
};
|
|
936
|
+
fs.writeJsonSync(configPath, config, { spaces: 2 });
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* Setup Claude Code automatic plugin registration
|
|
940
|
+
* Creates .claude/settings.json with extraKnownMarketplaces
|
|
941
|
+
* This triggers Claude's native auto-install when users trust the folder
|
|
942
|
+
*/
|
|
943
|
+
function setupClaudePluginAutoRegistration(targetDir, language) {
|
|
944
|
+
const locale = getLocaleManager(language);
|
|
945
|
+
const settingsPath = path.join(targetDir, '.claude', 'settings.json');
|
|
946
|
+
// Check if marketplace files exist
|
|
947
|
+
const marketplacePath = path.join(targetDir, '.claude-plugin', 'marketplace.json');
|
|
948
|
+
if (!fs.existsSync(marketplacePath)) {
|
|
949
|
+
console.log(chalk.yellow(`\n${locale.t('cli', 'init.warnings.marketplaceNotFound')}`));
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
// Create settings.json with marketplace registration
|
|
953
|
+
const settings = {
|
|
954
|
+
extraKnownMarketplaces: {
|
|
955
|
+
specweave: {
|
|
956
|
+
source: {
|
|
957
|
+
source: 'local',
|
|
958
|
+
path: './.claude-plugin'
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
try {
|
|
964
|
+
fs.writeJsonSync(settingsPath, settings, { spaces: 2 });
|
|
965
|
+
console.log(chalk.green(`\nā
${locale.t('cli', 'init.success.pluginAutoSetup')}`));
|
|
966
|
+
console.log(chalk.gray(` ${locale.t('cli', 'init.info.pluginAutoSetupDetails')}`));
|
|
967
|
+
}
|
|
968
|
+
catch (error) {
|
|
969
|
+
throw new Error(`Failed to create .claude/settings.json: ${error.message}`);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
function showNextSteps(projectName, adapterName, language, usedDotNotation = false, pluginAutoInstalled = false) {
|
|
973
|
+
const locale = getLocaleManager(language);
|
|
651
974
|
console.log('');
|
|
652
|
-
console.log(chalk.cyan.bold('
|
|
975
|
+
console.log(chalk.cyan.bold(locale.t('cli', 'init.nextSteps.header')));
|
|
653
976
|
console.log('');
|
|
654
977
|
let stepNumber = 1;
|
|
655
978
|
// Only show "cd" step if we created a subdirectory
|
|
656
979
|
if (!usedDotNotation) {
|
|
657
|
-
console.log(` ${stepNumber}. ${chalk.white(
|
|
980
|
+
console.log(` ${stepNumber}. ${chalk.white(locale.t('cli', 'init.nextSteps.cd', { projectName }))}`);
|
|
658
981
|
console.log('');
|
|
659
982
|
stepNumber++;
|
|
660
983
|
}
|
|
661
984
|
// Adapter-specific instructions
|
|
662
985
|
if (adapterName === 'claude') {
|
|
663
|
-
console.log(` ${stepNumber}. ${chalk.white('
|
|
664
|
-
console.log(` ${chalk.gray('"Build a real estate listing platform"')}`);
|
|
986
|
+
console.log(` ${stepNumber}. ${chalk.white(locale.t('cli', 'init.nextSteps.claude.step1'))}`);
|
|
665
987
|
console.log('');
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
988
|
+
stepNumber++;
|
|
989
|
+
// Only show manual install if auto-install failed
|
|
990
|
+
if (!pluginAutoInstalled) {
|
|
991
|
+
console.log(` ${stepNumber}. ${chalk.yellow.bold('ā ļø ' + locale.t('cli', 'init.nextSteps.claude.step2'))}`);
|
|
992
|
+
console.log(` ${chalk.cyan.bold(locale.t('cli', 'init.nextSteps.claude.installCore'))}`);
|
|
993
|
+
console.log(` ${chalk.gray('ā Required for slash commands like /specweave:inc')}`);
|
|
994
|
+
console.log('');
|
|
995
|
+
stepNumber++;
|
|
996
|
+
}
|
|
997
|
+
console.log(` ${stepNumber}. ${chalk.white(locale.t('cli', 'init.nextSteps.claude.step3'))}`);
|
|
998
|
+
console.log(` ${chalk.gray(locale.t('cli', 'init.nextSteps.claude.installGitHub'))}`);
|
|
999
|
+
console.log(` ${chalk.gray(locale.t('cli', 'init.nextSteps.claude.installFrontend'))}`);
|
|
1000
|
+
console.log(` ${chalk.gray('...or let SpecWeave suggest plugins automatically')}`);
|
|
1001
|
+
console.log('');
|
|
1002
|
+
stepNumber++;
|
|
1003
|
+
console.log(` ${stepNumber}. ${chalk.white(locale.t('cli', 'init.nextSteps.claude.step4'))}`);
|
|
1004
|
+
console.log(` ${chalk.cyan(locale.t('cli', 'init.nextSteps.claude.example'))}`);
|
|
1005
|
+
console.log(` ${chalk.gray(locale.t('cli', 'init.nextSteps.claude.autoActivate'))}`);
|
|
670
1006
|
}
|
|
671
1007
|
else if (adapterName === 'cursor') {
|
|
672
|
-
console.log(` ${stepNumber}. ${chalk.white('
|
|
1008
|
+
console.log(` ${stepNumber}. ${chalk.white(locale.t('cli', 'init.nextSteps.cursor.step1'))}`);
|
|
673
1009
|
console.log('');
|
|
674
|
-
console.log(` ${stepNumber + 1}. ${chalk.white('
|
|
675
|
-
console.log(`
|
|
1010
|
+
console.log(` ${stepNumber + 1}. ${chalk.white(locale.t('cli', 'init.nextSteps.cursor.step2'))}`);
|
|
1011
|
+
console.log(` ${locale.t('cli', 'init.nextSteps.cursor.guide')}`);
|
|
676
1012
|
console.log('');
|
|
677
|
-
console.log(` ${stepNumber + 2}. ${chalk.white('
|
|
678
|
-
console.log(`
|
|
1013
|
+
console.log(` ${stepNumber + 2}. ${chalk.white(locale.t('cli', 'init.nextSteps.cursor.step3'))}`);
|
|
1014
|
+
console.log(` ${locale.t('cli', 'init.nextSteps.cursor.shortcuts')}`);
|
|
679
1015
|
}
|
|
680
1016
|
else if (adapterName === 'copilot') {
|
|
681
|
-
console.log(` ${stepNumber}. ${chalk.white('
|
|
1017
|
+
console.log(` ${stepNumber}. ${chalk.white(locale.t('cli', 'init.nextSteps.copilot.step1'))}`);
|
|
682
1018
|
console.log('');
|
|
683
|
-
console.log(` ${stepNumber + 1}. ${chalk.white('
|
|
684
|
-
console.log(`
|
|
1019
|
+
console.log(` ${stepNumber + 1}. ${chalk.white(locale.t('cli', 'init.nextSteps.copilot.step2'))}`);
|
|
1020
|
+
console.log(` ${locale.t('cli', 'init.nextSteps.copilot.action')}`);
|
|
685
1021
|
console.log('');
|
|
686
|
-
console.log(` ${stepNumber + 2}. ${chalk.white('
|
|
687
|
-
console.log(`
|
|
1022
|
+
console.log(` ${stepNumber + 2}. ${chalk.white(locale.t('cli', 'init.nextSteps.copilot.step3'))}`);
|
|
1023
|
+
console.log(` ${locale.t('cli', 'init.nextSteps.copilot.example')}`);
|
|
688
1024
|
}
|
|
689
1025
|
else if (adapterName === 'generic') {
|
|
690
|
-
console.log(` ${stepNumber}. ${chalk.white('
|
|
1026
|
+
console.log(` ${stepNumber}. ${chalk.white(locale.t('cli', 'init.nextSteps.generic.step1'))}`);
|
|
691
1027
|
console.log('');
|
|
692
|
-
console.log(` ${stepNumber + 1}. ${chalk.white('
|
|
693
|
-
console.log(`
|
|
1028
|
+
console.log(` ${stepNumber + 1}. ${chalk.white(locale.t('cli', 'init.nextSteps.generic.step2'))}`);
|
|
1029
|
+
console.log(` ${locale.t('cli', 'init.nextSteps.generic.compatibility')}`);
|
|
694
1030
|
}
|
|
695
1031
|
console.log('');
|
|
696
|
-
console.log(chalk.green.bold('
|
|
1032
|
+
console.log(chalk.green.bold(locale.t('cli', 'init.nextSteps.footer')));
|
|
697
1033
|
console.log('');
|
|
698
|
-
console.log(chalk.gray('
|
|
699
|
-
console.log(chalk.gray('
|
|
1034
|
+
console.log(chalk.gray(locale.t('cli', 'init.nextSteps.docsLink')));
|
|
1035
|
+
console.log(chalk.gray(locale.t('cli', 'init.nextSteps.githubLink')));
|
|
700
1036
|
console.log('');
|
|
701
1037
|
}
|
|
702
1038
|
//# sourceMappingURL=init.js.map
|