create-specfuse 0.2.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.
Files changed (123) hide show
  1. package/README.md +203 -0
  2. package/bin/create-specfuse.js +2 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +35 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/prompts.d.ts +3 -0
  8. package/dist/prompts.d.ts.map +1 -0
  9. package/dist/prompts.js +103 -0
  10. package/dist/prompts.js.map +1 -0
  11. package/dist/scaffolder.d.ts +3 -0
  12. package/dist/scaffolder.d.ts.map +1 -0
  13. package/dist/scaffolder.js +233 -0
  14. package/dist/scaffolder.js.map +1 -0
  15. package/dist/stacks/bash.d.ts +5 -0
  16. package/dist/stacks/bash.d.ts.map +1 -0
  17. package/dist/stacks/bash.js +66 -0
  18. package/dist/stacks/bash.js.map +1 -0
  19. package/dist/stacks/cpp-cmake.d.ts +5 -0
  20. package/dist/stacks/cpp-cmake.d.ts.map +1 -0
  21. package/dist/stacks/cpp-cmake.js +74 -0
  22. package/dist/stacks/cpp-cmake.js.map +1 -0
  23. package/dist/stacks/detect.d.ts +11 -0
  24. package/dist/stacks/detect.d.ts.map +1 -0
  25. package/dist/stacks/detect.js +104 -0
  26. package/dist/stacks/detect.js.map +1 -0
  27. package/dist/stacks/dotnet.d.ts +5 -0
  28. package/dist/stacks/dotnet.d.ts.map +1 -0
  29. package/dist/stacks/dotnet.js +68 -0
  30. package/dist/stacks/dotnet.js.map +1 -0
  31. package/dist/stacks/elixir.d.ts +5 -0
  32. package/dist/stacks/elixir.d.ts.map +1 -0
  33. package/dist/stacks/elixir.js +68 -0
  34. package/dist/stacks/elixir.js.map +1 -0
  35. package/dist/stacks/go.d.ts +5 -0
  36. package/dist/stacks/go.d.ts.map +1 -0
  37. package/dist/stacks/go.js +68 -0
  38. package/dist/stacks/go.js.map +1 -0
  39. package/dist/stacks/index.d.ts +7 -0
  40. package/dist/stacks/index.d.ts.map +1 -0
  41. package/dist/stacks/index.js +84 -0
  42. package/dist/stacks/index.js.map +1 -0
  43. package/dist/stacks/java-gradle.d.ts +5 -0
  44. package/dist/stacks/java-gradle.d.ts.map +1 -0
  45. package/dist/stacks/java-gradle.js +69 -0
  46. package/dist/stacks/java-gradle.js.map +1 -0
  47. package/dist/stacks/java-maven.d.ts +5 -0
  48. package/dist/stacks/java-maven.d.ts.map +1 -0
  49. package/dist/stacks/java-maven.js +67 -0
  50. package/dist/stacks/java-maven.js.map +1 -0
  51. package/dist/stacks/kotlin.d.ts +5 -0
  52. package/dist/stacks/kotlin.d.ts.map +1 -0
  53. package/dist/stacks/kotlin.js +69 -0
  54. package/dist/stacks/kotlin.js.map +1 -0
  55. package/dist/stacks/php.d.ts +5 -0
  56. package/dist/stacks/php.d.ts.map +1 -0
  57. package/dist/stacks/php.js +68 -0
  58. package/dist/stacks/php.js.map +1 -0
  59. package/dist/stacks/python-fastapi.d.ts +5 -0
  60. package/dist/stacks/python-fastapi.d.ts.map +1 -0
  61. package/dist/stacks/python-fastapi.js +75 -0
  62. package/dist/stacks/python-fastapi.js.map +1 -0
  63. package/dist/stacks/ruby.d.ts +5 -0
  64. package/dist/stacks/ruby.d.ts.map +1 -0
  65. package/dist/stacks/ruby.js +69 -0
  66. package/dist/stacks/ruby.js.map +1 -0
  67. package/dist/stacks/rust.d.ts +5 -0
  68. package/dist/stacks/rust.d.ts.map +1 -0
  69. package/dist/stacks/rust.js +65 -0
  70. package/dist/stacks/rust.js.map +1 -0
  71. package/dist/stacks/scala-sbt.d.ts +5 -0
  72. package/dist/stacks/scala-sbt.d.ts.map +1 -0
  73. package/dist/stacks/scala-sbt.js +68 -0
  74. package/dist/stacks/scala-sbt.js.map +1 -0
  75. package/dist/stacks/schema.d.ts +91 -0
  76. package/dist/stacks/schema.d.ts.map +1 -0
  77. package/dist/stacks/schema.js +23 -0
  78. package/dist/stacks/schema.js.map +1 -0
  79. package/dist/stacks/swift.d.ts +5 -0
  80. package/dist/stacks/swift.d.ts.map +1 -0
  81. package/dist/stacks/swift.js +69 -0
  82. package/dist/stacks/swift.js.map +1 -0
  83. package/dist/stacks/typescript-react.d.ts +5 -0
  84. package/dist/stacks/typescript-react.d.ts.map +1 -0
  85. package/dist/stacks/typescript-react.js +73 -0
  86. package/dist/stacks/typescript-react.js.map +1 -0
  87. package/dist/templates/claude-md.d.ts +4 -0
  88. package/dist/templates/claude-md.d.ts.map +1 -0
  89. package/dist/templates/claude-md.js +241 -0
  90. package/dist/templates/claude-md.js.map +1 -0
  91. package/dist/templates/claude-settings.d.ts +3 -0
  92. package/dist/templates/claude-settings.d.ts.map +1 -0
  93. package/dist/templates/claude-settings.js +27 -0
  94. package/dist/templates/claude-settings.js.map +1 -0
  95. package/dist/templates/gitignore.d.ts +3 -0
  96. package/dist/templates/gitignore.d.ts.map +1 -0
  97. package/dist/templates/gitignore.js +39 -0
  98. package/dist/templates/gitignore.js.map +1 -0
  99. package/dist/templates/grill-me-skill.d.ts +2 -0
  100. package/dist/templates/grill-me-skill.d.ts.map +1 -0
  101. package/dist/templates/grill-me-skill.js +20 -0
  102. package/dist/templates/grill-me-skill.js.map +1 -0
  103. package/dist/templates/openspec-config.d.ts +3 -0
  104. package/dist/templates/openspec-config.d.ts.map +1 -0
  105. package/dist/templates/openspec-config.js +8 -0
  106. package/dist/templates/openspec-config.js.map +1 -0
  107. package/dist/types.d.ts +35 -0
  108. package/dist/types.d.ts.map +1 -0
  109. package/dist/types.js +2 -0
  110. package/dist/types.js.map +1 -0
  111. package/dist/utils/fs.d.ts +5 -0
  112. package/dist/utils/fs.d.ts.map +1 -0
  113. package/dist/utils/fs.js +17 -0
  114. package/dist/utils/fs.js.map +1 -0
  115. package/dist/utils/git.d.ts +4 -0
  116. package/dist/utils/git.d.ts.map +1 -0
  117. package/dist/utils/git.js +21 -0
  118. package/dist/utils/git.js.map +1 -0
  119. package/dist/utils/tools.d.ts +7 -0
  120. package/dist/utils/tools.d.ts.map +1 -0
  121. package/dist/utils/tools.js +82 -0
  122. package/dist/utils/tools.js.map +1 -0
  123. package/package.json +44 -0
package/README.md ADDED
@@ -0,0 +1,203 @@
1
+ # SpecFuse
2
+
3
+ 将 AI 编码从即兴发挥改造为工程流水线。
4
+
5
+ SpecFuse 不发明新工具——它把 OpenSpec、Superpowers、Grill-me 按正确的顺序编排成一条四拍流水线:**Think → Grill → Do → Verify**。一条命令注入到任何项目。
6
+
7
+ ## 快速开始
8
+
9
+ ```bash
10
+ npm create specfuse@latest
11
+ ```
12
+
13
+ 交互式引导你选择技术栈,生成项目骨架和完整的工作流配置。无需全局安装,始终拉取最新版。
14
+
15
+ ```bash
16
+ # 指定目录
17
+ npm create specfuse@latest my-app
18
+
19
+ # 指定技术栈,跳过交互
20
+ npm create specfuse@latest my-app -- --stack rust --yes
21
+ ```
22
+
23
+ ### 前置依赖
24
+
25
+ - **Node.js >= 18**(推荐通过 [nvm](https://github.com/nvm-sh/nvm) 安装)
26
+
27
+ ### 可选组件
28
+
29
+ SpecFuse 生成的工作流依赖以下组件实现完整能力,但它们不是硬依赖:
30
+
31
+ ```bash
32
+ # OpenSpec CLI — 流程引擎
33
+ npm install -g @fission-ai/openspec
34
+
35
+ # Superpowers — Claude Code 行为约束插件(在 Claude Code 内执行)
36
+ /plugins add obra/superpowers
37
+ ```
38
+
39
+ > 未安装时,生成的 CLAUDE.md 仍然有效,只是 `/opsx:*` 命令和 Superpowers 技能不可用。
40
+
41
+ ---
42
+
43
+ ## 它做了什么
44
+
45
+ 运行后在目标目录生成:
46
+
47
+ ```
48
+ my-app/
49
+ ├── CLAUDE.md # 融合方法论 + 流水线纪律规则
50
+ ├── .gitignore # 栈特化忽略规则
51
+ ├── .claude/
52
+ │ └── settings.local.json # 权限白名单
53
+ └── openspec/
54
+ ├── config.yaml # 栈特化 spec 规则
55
+ ├── specs/
56
+ └── changes/
57
+ └── archive/
58
+ ```
59
+
60
+ 如果检测到已安装 `@fission-ai/openspec`,还会自动注册 OpenSpec 技能和 `/opsx:*` 命令。
61
+
62
+ ---
63
+
64
+ ## 四拍流水线
65
+
66
+ 初始化完成后,在项目中启动 Claude Code,按以下节奏开发:
67
+
68
+ ```
69
+ Think /opsx:new 或 /opsx:propose
70
+ ↓ 激活 Brainstorming(苏格拉底式一问一答)
71
+ ↓ 生成 proposal → design → specs → tasks
72
+
73
+ Grill /grill-me
74
+ ↓ AI 反向质问设计,逐条 blocking/non-blocking
75
+ ↓ 修补制品后进入实施
76
+
77
+ Do /opsx:apply
78
+ ↓ 严格 TDD:写失败测试 → 最小实现 → 粘贴证据
79
+ ↓ 每个任务完成前必须有终端输出作为证据
80
+
81
+ Verify /opsx:verify → /opsx:archive
82
+ ↓ 全量测试 + lint 零警告 → 归档
83
+ ```
84
+
85
+ ### 内置纪律(自动执行,无需手动记忆)
86
+
87
+ | 阶段 | 强制行为 |
88
+ |------|----------|
89
+ | Think | 一次一问,2-3 种方案对比,Non-goals + Trade-offs |
90
+ | Grill | 多维度审查,blocking 问题必须解决才能进入实施 |
91
+ | Do | Red-Green-Refactor,禁止跳过测试 |
92
+ | Verify | 必须粘贴终端原始输出,不接受"应该能跑" |
93
+
94
+ ---
95
+
96
+ ## 已有项目初始化
97
+
98
+ ```bash
99
+ cd existing-project
100
+ npm create specfuse@latest .
101
+ ```
102
+
103
+ 智能合并策略,不覆盖已有内容:
104
+
105
+ | 文件 | 行为 |
106
+ |------|------|
107
+ | `CLAUDE.md` | 有 `<!-- FUSION:START/END -->` 标记 → 替换标记内段落;无标记 → 追加 |
108
+ | `.gitignore` | 追加缺失模式,不重复 |
109
+ | `.claude/settings.local.json` | 合并权限列表 |
110
+ | `openspec/config.yaml` | 已存在 → 跳过 |
111
+
112
+ ---
113
+
114
+ ## 内置技术栈
115
+
116
+ | 栈 | ID | 构建 | 测试 | Lint |
117
+ |---|---|---|---|---|
118
+ | Rust | `rust` | `cargo build` | `cargo test` | `cargo clippy -- -D warnings` |
119
+ | Go | `go` | `go build ./...` | `go test ./...` | `golangci-lint run` |
120
+ | TypeScript + React | `typescript-react` | `npm run build` | `npx vitest run` | `npx eslint .` |
121
+ | Python + FastAPI | `python-fastapi` | `pip install -e .` | `pytest tests/ -v` | `ruff check .` |
122
+ | Java (Maven) | `java-maven` | `mvn package` | `mvn test` | `mvn checkstyle:check` |
123
+ | Java (Gradle) | `java-gradle` | `./gradlew build` | `./gradlew test` | `./gradlew checkstyleMain` |
124
+ | C++ (CMake) | `cpp-cmake` | `cmake --build build` | `ctest --test-dir build` | `clang-tidy` |
125
+ | Ruby | `ruby` | — | `bundle exec rspec` | `bundle exec rubocop` |
126
+ | PHP | `php` | `composer install` | `./vendor/bin/phpunit` | `./vendor/bin/phpstan` |
127
+ | Kotlin | `kotlin` | `./gradlew build` | `./gradlew test` | `./gradlew ktlintCheck` |
128
+ | Swift | `swift` | `swift build` | `swift test` | `swiftlint` |
129
+ | Elixir | `elixir` | `mix compile` | `mix test` | `mix credo` |
130
+ | Scala (sbt) | `scala-sbt` | `sbt compile` | `sbt test` | `sbt scalafmtCheck` |
131
+ | .NET | `dotnet` | `dotnet build` | `dotnet test` | `dotnet format --verify-no-changes` |
132
+ | Bash | `bash` | — | `bats tests/` | `shellcheck **/*.sh` |
133
+
134
+ ### 自定义栈
135
+
136
+ 创建 YAML 文件定义你的栈:
137
+
138
+ ```yaml
139
+ id: java-spring
140
+ label: "Java + Spring Boot"
141
+ languages: [Java]
142
+ framework: Spring Boot
143
+ architecture: Layered (Controller → Service → Repository)
144
+ commands:
145
+ build: ./gradlew build
146
+ test: ./gradlew test
147
+ lint: ./gradlew checkstyleMain
148
+ format: ./gradlew spotlessApply
149
+ permissions:
150
+ - "Bash(./gradlew *)"
151
+ gitignorePatterns:
152
+ - "/build/"
153
+ - "/.gradle/"
154
+ ```
155
+
156
+ ```bash
157
+ npm create specfuse@latest my-app -- --stack-from ./java-spring.yaml
158
+ ```
159
+
160
+ ---
161
+
162
+ ## CLI 参考
163
+
164
+ ```
165
+ Usage: create-specfuse [options] [project-name]
166
+
167
+ Arguments:
168
+ project-name 目标目录(省略或 "." 表示当前目录)
169
+
170
+ Options:
171
+ --stack <id> 指定内置技术栈
172
+ --stack-from <path> 加载自定义栈配置(YAML/JSON)
173
+ -y, --yes 非交互模式(CI 友好)
174
+ -V, --version 显示版本号
175
+ -h, --help 显示帮助
176
+ ```
177
+
178
+ ---
179
+
180
+ ## 为什么需要编排
181
+
182
+ 你手里可能已经有 OpenSpec、Superpowers、Grill-me——但谁来记住"现在该激活什么"?
183
+
184
+ - **你来记** → 你会忘。第三个小需求时你会想"太简单了不需要 brainstorm",然后写到一半发现方向错了。
185
+ - **流水线来记** → 每个命令背后自动调度对应能力。调用"开始实施",TDD 铁律就自动生效。
186
+
187
+ 这就是融合和组合的区别:组合是你有三个好工具,融合是一条流水线让工具在正确时刻自动接力。
188
+
189
+ ---
190
+
191
+ ## 开发
192
+
193
+ ```bash
194
+ npm install
195
+ npm run build
196
+ npm test
197
+ ```
198
+
199
+ 新增栈模板:在 `src/stacks/` 下创建文件并注册到 `src/stacks/index.ts`。
200
+
201
+ ## License
202
+
203
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/index.js';
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { readFileSync } from 'node:fs';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { dirname, resolve } from 'node:path';
6
+ import { collectProjectConfig } from './prompts.js';
7
+ import { scaffold } from './scaffolder.js';
8
+ import { loadCustomStack } from './stacks/index.js';
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
+ const pkg = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'utf-8'));
11
+ const program = new Command();
12
+ program
13
+ .name('create-specfuse')
14
+ .description('SpecFuse — AI engineering pipeline scaffolder.\n\nInjects OpenSpec workflow + Superpowers discipline into any project.\nThink → Grill → Do → Verify, one command at a time.')
15
+ .version(pkg.version)
16
+ .argument('[project-name]', 'Target directory (omit or use "." to init in current directory)')
17
+ .option('--stack <id>', 'Built-in stack: rust, go, typescript-react, python-fastapi, bash, java-maven, java-gradle, cpp-cmake, ruby, php, kotlin, swift, elixir, scala-sbt, dotnet')
18
+ .option('--stack-from <path>', 'Custom stack profile (YAML/JSON)')
19
+ .option('-y, --yes', 'Non-interactive mode (use defaults, CI-friendly)')
20
+ .action(async (projectName, opts) => {
21
+ try {
22
+ let customStack;
23
+ if (opts.stackFrom) {
24
+ customStack = await loadCustomStack(opts.stackFrom);
25
+ }
26
+ const config = await collectProjectConfig(projectName, opts.stack, customStack, opts.yes);
27
+ await scaffold(config);
28
+ }
29
+ catch (err) {
30
+ console.error(`\nError: ${err.message}\n`);
31
+ process.exit(1);
32
+ }
33
+ });
34
+ program.parse();
35
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAExF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,iBAAiB,CAAC;KACvB,WAAW,CAAC,6KAA6K,CAAC;KAC1L,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;KACpB,QAAQ,CAAC,gBAAgB,EAAE,iEAAiE,CAAC;KAC7F,MAAM,CAAC,cAAc,EAAE,2JAA2J,CAAC;KACnL,MAAM,CAAC,qBAAqB,EAAE,kCAAkC,CAAC;KACjE,MAAM,CAAC,WAAW,EAAE,kDAAkD,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,WAA+B,EAAE,IAA2D,EAAE,EAAE;IAC7G,IAAI,CAAC;QACH,IAAI,WAAW,CAAC;QAChB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,WAAW,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1F,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,YAAa,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { StackProfile, ProjectConfig } from './types.js';
2
+ export declare function collectProjectConfig(projectNameArg?: string, stackArg?: string, customStack?: StackProfile, skipPrompts?: boolean): Promise<ProjectConfig>;
3
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE9D,wBAAsB,oBAAoB,CACxC,cAAc,CAAC,EAAE,MAAM,EACvB,QAAQ,CAAC,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,YAAY,EAC1B,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,aAAa,CAAC,CA4CxB"}
@@ -0,0 +1,103 @@
1
+ import path from 'node:path';
2
+ import { select, confirm } from '@inquirer/prompts';
3
+ import { getBuiltinStacks } from './stacks/index.js';
4
+ import { detectStacks } from './stacks/detect.js';
5
+ export async function collectProjectConfig(projectNameArg, stackArg, customStack, skipPrompts) {
6
+ const isExisting = projectNameArg === undefined || projectNameArg === '.';
7
+ let projectName;
8
+ let targetDir;
9
+ if (isExisting) {
10
+ targetDir = process.cwd();
11
+ projectName = path.basename(targetDir);
12
+ }
13
+ else {
14
+ projectName = projectNameArg;
15
+ if (!/^[a-zA-Z0-9_-]+$/.test(projectName)) {
16
+ throw new Error('Project name can only contain letters, digits, hyphens, underscores');
17
+ }
18
+ targetDir = path.join(process.cwd(), projectName);
19
+ }
20
+ let stack;
21
+ if (customStack) {
22
+ stack = customStack;
23
+ }
24
+ else if (stackArg) {
25
+ const found = getBuiltinStacks().find((s) => s.id === stackArg);
26
+ if (!found) {
27
+ const ids = getBuiltinStacks().map((s) => s.id).join(', ');
28
+ throw new Error(`Unknown stack "${stackArg}". Available: ${ids}`);
29
+ }
30
+ stack = found;
31
+ }
32
+ else if (skipPrompts) {
33
+ throw new Error('--stack is required with --yes');
34
+ }
35
+ else if (isExisting) {
36
+ stack = await detectAndSelect(targetDir);
37
+ }
38
+ else {
39
+ stack = await promptFullStackList();
40
+ }
41
+ const initGit = isExisting
42
+ ? false
43
+ : (skipPrompts ? true : await confirm({ message: 'Initialize git repository?', default: true }));
44
+ const initOpenspec = skipPrompts ? true : await confirm({ message: 'Initialize OpenSpec?', default: true });
45
+ const initCodegraph = skipPrompts ? true : await confirm({ message: 'Enable CodeGraph code knowledge graph?', default: true });
46
+ return { projectName, stack, initGit, initOpenspec, initCodegraph, targetDir, isExisting };
47
+ }
48
+ async function detectAndSelect(targetDir) {
49
+ const detected = await detectStacks(targetDir);
50
+ const stacks = getBuiltinStacks();
51
+ if (detected.length === 1) {
52
+ const found = stacks.find((s) => s.id === detected[0]);
53
+ if (found) {
54
+ const useDetected = await confirm({ message: `Detected stack: ${found.label}. Use it?`, default: true });
55
+ if (useDetected)
56
+ return found;
57
+ return promptFullStackList();
58
+ }
59
+ }
60
+ if (detected.length > 1) {
61
+ const detectedStacks = detected
62
+ .map((id) => stacks.find((s) => s.id === id))
63
+ .filter((s) => !!s);
64
+ const choices = [
65
+ ...detectedStacks.map((s) => ({ name: `${s.label} (detected)`, value: s.id })),
66
+ { name: 'Other...', value: '__other__' },
67
+ ];
68
+ const stackId = await select({ message: 'Detected multiple stacks. Select primary:', choices });
69
+ if (stackId === '__other__') {
70
+ return promptFullStackList();
71
+ }
72
+ return stacks.find((s) => s.id === stackId);
73
+ }
74
+ return promptFullStackList();
75
+ }
76
+ async function promptFullStackList() {
77
+ const stacks = getBuiltinStacks();
78
+ const choices = [
79
+ { name: 'Skip (decide later)', value: '__skip__' },
80
+ ...stacks.map((s) => ({ name: s.label, value: s.id })),
81
+ ];
82
+ const stackId = await select({
83
+ message: 'Tech stack:',
84
+ choices,
85
+ });
86
+ if (stackId === '__skip__') {
87
+ return {
88
+ id: 'generic',
89
+ label: 'Generic',
90
+ languages: [],
91
+ architecture: 'Not specified',
92
+ commands: { build: 'echo "no build configured"', test: 'echo "no test configured"', lint: 'echo "no lint configured"' },
93
+ errorHandling: 'Not specified',
94
+ concurrency: 'Not specified',
95
+ permissions: [],
96
+ gitignorePatterns: [],
97
+ openspecContext: 'Tech stack not yet configured. Set up later with create-specfuse --stack <id>',
98
+ openspecRules: {},
99
+ };
100
+ }
101
+ return stacks.find((s) => s.id === stackId);
102
+ }
103
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ProjectConfig } from './types.js';
2
+ export declare function scaffold(config: ProjectConfig): Promise<void>;
3
+ //# sourceMappingURL=scaffolder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffolder.d.ts","sourceRoot":"","sources":["../src/scaffolder.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA0EhD,wBAAsB,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA4KnE"}
@@ -0,0 +1,233 @@
1
+ import path from 'node:path';
2
+ import { access, readFile } from 'node:fs/promises';
3
+ import { existsSync, readFileSync } from 'node:fs';
4
+ import chalk from 'chalk';
5
+ import ora from 'ora';
6
+ import { composeGitignore } from './templates/gitignore.js';
7
+ import { composeClaudeSettings } from './templates/claude-settings.js';
8
+ import { composeOpenspecConfig } from './templates/openspec-config.js';
9
+ import { composeGrillMeSkill } from './templates/grill-me-skill.js';
10
+ import { composeCLAUDEmd } from './templates/claude-md.js';
11
+ import { createDir, writeText, writeJSON, writeYAML } from './utils/fs.js';
12
+ import { gitInit, gitInitialCommit } from './utils/git.js';
13
+ import { detectCodegraph, installCodegraph, initCodegraph, detectOpenspec, installOpenspec, initOpenspec } from './utils/tools.js';
14
+ function hasSuperpowersPlugin() {
15
+ const pluginsPath = path.join(process.env.HOME || '', '.claude', 'plugins', 'installed_plugins.json');
16
+ if (!existsSync(pluginsPath))
17
+ return false;
18
+ try {
19
+ const data = JSON.parse(readFileSync(pluginsPath, 'utf-8'));
20
+ return Object.keys(data.plugins || {}).some((k) => k.startsWith('superpowers'));
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ async function fileExists(filePath) {
27
+ try {
28
+ await access(filePath);
29
+ return true;
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ async function readTextSafe(filePath) {
36
+ try {
37
+ return await readFile(filePath, 'utf-8');
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ }
43
+ function mergeFusionIntoCLAUDEmd(existing, fusionBlock) {
44
+ const startMarker = '<!-- FUSION:START -->';
45
+ const endMarker = '<!-- FUSION:END -->';
46
+ const startIdx = existing.indexOf(startMarker);
47
+ const endIdx = existing.indexOf(endMarker);
48
+ const newCLAUDEmd = fusionBlock;
49
+ const fusionStart = newCLAUDEmd.indexOf(startMarker);
50
+ const fusionEnd = newCLAUDEmd.indexOf(endMarker);
51
+ const fusionContent = newCLAUDEmd.slice(fusionStart, fusionEnd + endMarker.length);
52
+ if (startIdx !== -1 && endIdx !== -1) {
53
+ return existing.slice(0, startIdx) + fusionContent + existing.slice(endIdx + endMarker.length);
54
+ }
55
+ return existing.trimEnd() + '\n\n---\n\n' + fusionContent + '\n';
56
+ }
57
+ function mergeGitignore(existing, generated) {
58
+ const existingLines = new Set(existing.split('\n').map((l) => l.trim()).filter(Boolean));
59
+ const newLines = generated.split('\n').filter((l) => {
60
+ const trimmed = l.trim();
61
+ return trimmed && !trimmed.startsWith('#') && !existingLines.has(trimmed);
62
+ });
63
+ if (newLines.length === 0)
64
+ return existing;
65
+ return existing.trimEnd() + '\n\n# Added by specfuse\n' + newLines.join('\n') + '\n';
66
+ }
67
+ function mergeClaudeSettings(existing, generated) {
68
+ const existingPerms = existing?.permissions?.allow ?? [];
69
+ const generatedPerms = generated?.permissions?.allow ?? [];
70
+ const merged = [...new Set([...existingPerms, ...generatedPerms])];
71
+ return { ...existing, permissions: { ...existing?.permissions, allow: merged } };
72
+ }
73
+ export async function scaffold(config) {
74
+ const { targetDir, stack, projectName, isExisting } = config;
75
+ const ctx = { projectName, stack };
76
+ if (!isExisting && await fileExists(targetDir)) {
77
+ throw new Error(`Directory "${targetDir}" already exists. Omit project name to init in current directory.`);
78
+ }
79
+ const spinner = ora(isExisting ? 'Initializing specfuse in current directory...' : 'Scaffolding project...').start();
80
+ await createDir(targetDir);
81
+ // .gitignore
82
+ spinner.text = 'Writing .gitignore...';
83
+ const gitignorePath = path.join(targetDir, '.gitignore');
84
+ const existingGitignore = await readTextSafe(gitignorePath);
85
+ const generatedGitignore = composeGitignore(stack);
86
+ if (existingGitignore) {
87
+ await writeText(gitignorePath, mergeGitignore(existingGitignore, generatedGitignore));
88
+ }
89
+ else {
90
+ await writeText(gitignorePath, generatedGitignore);
91
+ }
92
+ // CLAUDE.md
93
+ spinner.text = 'Writing CLAUDE.md...';
94
+ const claudeMdPath = path.join(targetDir, 'CLAUDE.md');
95
+ const existingCLAUDEmd = await readTextSafe(claudeMdPath);
96
+ const generatedCLAUDEmd = composeCLAUDEmd(ctx);
97
+ if (existingCLAUDEmd) {
98
+ await writeText(claudeMdPath, mergeFusionIntoCLAUDEmd(existingCLAUDEmd, generatedCLAUDEmd));
99
+ }
100
+ else {
101
+ await writeText(claudeMdPath, generatedCLAUDEmd);
102
+ }
103
+ // .claude/settings.local.json
104
+ spinner.text = 'Writing .claude/settings.local.json...';
105
+ const settingsPath = path.join(targetDir, '.claude', 'settings.local.json');
106
+ const existingSettings = await readTextSafe(settingsPath);
107
+ const generatedSettings = composeClaudeSettings(stack);
108
+ if (existingSettings) {
109
+ try {
110
+ const parsed = JSON.parse(existingSettings);
111
+ await writeJSON(settingsPath, mergeClaudeSettings(parsed, generatedSettings));
112
+ }
113
+ catch {
114
+ await writeJSON(settingsPath, generatedSettings);
115
+ }
116
+ }
117
+ else {
118
+ await writeJSON(settingsPath, generatedSettings);
119
+ }
120
+ // Grill-me skill
121
+ spinner.text = 'Writing .claude/skills/grill-me/SKILL.md...';
122
+ const grillSkillPath = path.join(targetDir, '.claude', 'skills', 'grill-me', 'SKILL.md');
123
+ const existingGrillSkill = await readTextSafe(grillSkillPath);
124
+ if (!existingGrillSkill) {
125
+ await createDir(path.join(targetDir, '.claude', 'skills', 'grill-me'));
126
+ await writeText(grillSkillPath, composeGrillMeSkill());
127
+ }
128
+ // OpenSpec
129
+ if (config.initOpenspec) {
130
+ spinner.text = 'Setting up OpenSpec...';
131
+ await createDir(path.join(targetDir, 'openspec', 'specs'));
132
+ await createDir(path.join(targetDir, 'openspec', 'changes', 'archive'));
133
+ const configYamlPath = path.join(targetDir, 'openspec', 'config.yaml');
134
+ if (await fileExists(configYamlPath)) {
135
+ spinner.text = 'OpenSpec config.yaml already exists, skipping...';
136
+ }
137
+ else {
138
+ await writeYAML(configYamlPath, composeOpenspecConfig(ctx));
139
+ }
140
+ }
141
+ // Git
142
+ if (config.initGit) {
143
+ spinner.text = 'Initializing git...';
144
+ await gitInit(targetDir);
145
+ await gitInitialCommit(targetDir);
146
+ }
147
+ // OpenSpec skills
148
+ if (config.initOpenspec) {
149
+ spinner.text = 'Setting up OpenSpec...';
150
+ const hasOpenspec = await detectOpenspec();
151
+ if (hasOpenspec) {
152
+ const ok = await initOpenspec(targetDir);
153
+ if (!ok) {
154
+ spinner.warn('OpenSpec init failed. Run manually: openspec init --tools claude --force');
155
+ }
156
+ }
157
+ else {
158
+ spinner.text = 'Installing OpenSpec CLI...';
159
+ const installed = await installOpenspec();
160
+ if (installed) {
161
+ const ok = await initOpenspec(targetDir);
162
+ if (!ok) {
163
+ spinner.warn('OpenSpec installed but init failed. Run manually: openspec init --tools claude --force');
164
+ }
165
+ }
166
+ else {
167
+ spinner.warn('OpenSpec CLI installation failed. Install manually: npm i -g @fission-ai/openspec && openspec init');
168
+ }
169
+ }
170
+ }
171
+ // CodeGraph
172
+ if (config.initCodegraph) {
173
+ spinner.text = 'Setting up CodeGraph...';
174
+ const hasCodegraph = await detectCodegraph();
175
+ if (hasCodegraph) {
176
+ const ok = await initCodegraph(targetDir);
177
+ if (ok) {
178
+ spinner.text = 'CodeGraph initialized.';
179
+ }
180
+ else {
181
+ spinner.warn('CodeGraph init failed. Run manually: codegraph init -i && codegraph install');
182
+ }
183
+ }
184
+ else {
185
+ spinner.text = 'Installing CodeGraph...';
186
+ const installed = await installCodegraph();
187
+ if (installed) {
188
+ const ok = await initCodegraph(targetDir);
189
+ if (!ok) {
190
+ spinner.warn('CodeGraph installed but init failed. Run manually: codegraph init -i && codegraph install');
191
+ }
192
+ }
193
+ else {
194
+ spinner.warn('CodeGraph installation failed. Install manually:\n curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh | sh\n Then run: codegraph init -i && codegraph install');
195
+ }
196
+ }
197
+ }
198
+ spinner.succeed(isExisting ? 'SpecFuse initialized in current directory!' : 'Project scaffolded!');
199
+ console.log('');
200
+ console.log(chalk.bold(` ${projectName}/`));
201
+ const tag = (label) => isExisting ? `${label} ${chalk.yellow('(merged)')}` : label;
202
+ console.log(` CLAUDE.md ${chalk.dim(tag('Bridge declaration'))}`);
203
+ console.log(` .gitignore ${chalk.dim(tag(stack.label + ' patterns'))}`);
204
+ console.log(` .claude/settings.local.json ${chalk.dim(tag('Permissions'))}`);
205
+ if (config.initOpenspec) {
206
+ console.log(` openspec/config.yaml ${chalk.dim('Spec-driven config')}`);
207
+ }
208
+ console.log('');
209
+ console.log(chalk.bold(' Next steps:'));
210
+ if (!isExisting)
211
+ console.log(` cd ${projectName}`);
212
+ console.log(' claude');
213
+ console.log(' /opsx:propose # start your first change');
214
+ if (config.initCodegraph) {
215
+ const localBin = path.join(process.env.HOME || '', '.local', 'bin');
216
+ const inPath = (process.env.PATH || '').split(':').includes(localBin);
217
+ if (!inPath) {
218
+ console.log('');
219
+ console.log(chalk.yellow(' Note: ~/.local/bin is not in your PATH.'));
220
+ console.log(chalk.dim(' Add it to use codegraph directly:'));
221
+ console.log(chalk.dim(' echo \'export PATH="$HOME/.local/bin:$PATH"\' >> ~/.bashrc && source ~/.bashrc'));
222
+ }
223
+ }
224
+ if (!hasSuperpowersPlugin()) {
225
+ console.log('');
226
+ console.log(chalk.yellow(' Note: Superpowers plugin not detected.'));
227
+ console.log(chalk.dim(' The workflow requires the brainstorming skill from Superpowers.'));
228
+ console.log(chalk.dim(' Install in Claude Code:'));
229
+ console.log(chalk.dim(' /plugins add obra/superpowers'));
230
+ }
231
+ console.log('');
232
+ }
233
+ //# sourceMappingURL=scaffolder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffolder.js","sourceRoot":"","sources":["../src/scaffolder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { StackProfile } from '../types.js';
2
+ import type { DetectionConfig } from './detect.js';
3
+ export declare const bashStack: StackProfile;
4
+ export declare const bashDetectionConfig: DetectionConfig;
5
+ //# sourceMappingURL=bash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/stacks/bash.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,eAAO,MAAM,SAAS,EAAE,YAyDvB,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,eAMjC,CAAC"}