dream-wf 0.1.1 → 0.1.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/README.md +91 -24
- package/core/grill-prd-policy.md +2 -0
- package/core/workflow-profile.md +1 -0
- package/package.json +4 -3
- package/src/cli/index.js +192 -65
- package/src/deps/index.js +50 -0
- package/src/lib/catalog.js +82 -0
- package/src/lib/mcp.js +305 -0
- package/src/lib/platforms.js +13 -3
- package/src/lib/trellis.js +22 -2
- package/src/platforms/claude-code/index.js +31 -5
- package/src/platforms/codex/index.js +106 -0
- package/src/platforms/cursor/index.js +7 -3
- package/src/platforms/opencode/index.js +7 -3
- package/src/platforms/shared.js +11 -0
- package/src/tui/index.js +445 -0
- package/templates/hooks/claude-code/__pycache__/dream-wf-guard.cpython-314.pyc +0 -0
- package/templates/hooks/claude-code/dream-wf-guard.py +33 -11
- package/templates/hooks/codex/__pycache__/dream-wf-guard.cpython-314.pyc +0 -0
- package/templates/hooks/codex/dream-wf-guard.py +150 -0
- package/templates/hooks/cursor/__pycache__/dream-wf-guard.cpython-314.pyc +0 -0
- package/templates/hooks/cursor/dream-wf-guard.py +30 -11
- package/templates/hooks/opencode/dream-wf-guard.js +28 -10
- package/templates/rules/claude-code/dream-wf-block.md +2 -0
- package/templates/rules/codex/dream-wf-block.md +43 -0
- package/templates/rules/cursor/dream-wf.mdc +2 -1
- package/templates/rules/opencode/dream-wf-block.md +2 -0
- package/templates/skills/dream-wf-grill-prd/SKILL.md +54 -2
- package/templates/spec/guides/dream-wf-prd-policy.md +14 -0
package/README.md
CHANGED
|
@@ -1,44 +1,93 @@
|
|
|
1
1
|
# DREAM-WORKFLOW
|
|
2
2
|
|
|
3
|
-
面向
|
|
3
|
+
面向 Codex、Claude Code、OpenCode 和 Cursor 的 Workflow patch 安装聚合器。
|
|
4
4
|
|
|
5
|
-
`dream-wf` 不替代 Trellis。它是在 Trellis 之上安装一组项目级个人 workflow
|
|
5
|
+
`dream-wf` 不替代 Trellis。它是在 Trellis 之上安装一组项目级个人 workflow 约束,同时聚合配置 MCP servers 和 skills:
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
- Trellis
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
7
|
+
- 平台选择:Cursor / Claude Code / OpenCode / Codex
|
|
8
|
+
- Skill 安装:`dream-wf-grill-prd`(Trellis patch · grill-me 风格 PRD)、`dream-wf-mcp-policy`(MCP 优先级策略)
|
|
9
|
+
- MCP 配置:`fast-context-mcp`(代码语义检索)、`grok-search-mcp`(外部文档/实时网络检索)
|
|
10
|
+
- 交互式 TUI:上下选择、space 选中、enter 下一步/安装
|
|
11
|
+
- PRD 澄清自动采用 grill-me 风格,用户不需要显式提到 `dream-wf`
|
|
12
|
+
- Trellis 原生的任务生命周期、spec、hooks、skills、sub-agents、checks 和 finish-work 保持不变
|
|
13
|
+
- strict 模式会阻止无活跃任务或 PRD 未确认时的实现类操作
|
|
13
14
|
|
|
14
15
|
## 安装
|
|
15
16
|
|
|
17
|
+
### 交互式 TUI(推荐)
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx dream-wf
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
无参数时自动进入 TUI:
|
|
24
|
+
|
|
25
|
+
1. 第一步选择平台(claude code / codex / opencode / cursor)
|
|
26
|
+
2. 第二步选择要安装的 skills(默认全选)
|
|
27
|
+
3. 第三步选择要配置的 MCP servers(默认全选)
|
|
28
|
+
4. enter 确认安装
|
|
29
|
+
|
|
30
|
+
操作键:
|
|
31
|
+
|
|
32
|
+
- `↑/↓` 移动光标
|
|
33
|
+
- `space` 切换选中
|
|
34
|
+
- `a` 全选/全不选
|
|
35
|
+
- `enter` 下一步/确认
|
|
36
|
+
- `ctrl+c` 退出
|
|
37
|
+
|
|
38
|
+
### 命令行模式
|
|
39
|
+
|
|
16
40
|
```bash
|
|
17
41
|
npx dream-wf init -p cursor
|
|
18
42
|
npx dream-wf init -p claude
|
|
19
43
|
npx dream-wf init -p opencode
|
|
44
|
+
npx dream-wf init -p codex
|
|
20
45
|
```
|
|
21
46
|
|
|
22
|
-
`-p` 是必填参数。默认安装范围是项目级,默认模式是 `strict
|
|
47
|
+
`-p` 是必填参数。默认安装范围是项目级,默认模式是 `strict`,默认安装全部 skills 和 MCPs。
|
|
23
48
|
|
|
24
49
|
## 命令
|
|
25
50
|
|
|
26
51
|
```bash
|
|
27
|
-
npx dream-wf
|
|
28
|
-
npx dream-wf
|
|
29
|
-
npx dream-wf
|
|
52
|
+
npx dream-wf # 交互式 TUI
|
|
53
|
+
npx dream-wf interactive # 同上
|
|
54
|
+
npx dream-wf init -p <platform> [options]
|
|
55
|
+
npx dream-wf doctor -p <platform>
|
|
56
|
+
npx dream-wf update -p <platform>
|
|
30
57
|
```
|
|
31
58
|
|
|
32
59
|
参数:
|
|
33
60
|
|
|
34
61
|
```bash
|
|
35
|
-
-p cursor|claude|opencode
|
|
36
|
-
--mode strict|advisory
|
|
37
|
-
--
|
|
38
|
-
--
|
|
62
|
+
-p cursor|claude|opencode|codex # 必填
|
|
63
|
+
--mode strict|advisory # 默认 strict
|
|
64
|
+
--skills <id,id,...> # 指定 skill id,默认全部
|
|
65
|
+
--mcps <id,id,...> # 指定 mcp id,默认全部
|
|
66
|
+
--skip-skills # 不安装任何 skill
|
|
67
|
+
--skip-mcps # 不配置任何 mcp
|
|
68
|
+
--install-deps --developer <name> # 自动初始化 Trellis
|
|
39
69
|
```
|
|
40
70
|
|
|
41
|
-
|
|
71
|
+
Skill ids:
|
|
72
|
+
|
|
73
|
+
- `trellis-dream-wf-patch`(dream-wf-grill-prd)
|
|
74
|
+
- `dream-wf-mcp-policy`
|
|
75
|
+
|
|
76
|
+
MCP ids:
|
|
77
|
+
|
|
78
|
+
- `fast-context`(fast-context-mcp)
|
|
79
|
+
- `grok-search`(grok-search-mcp)
|
|
80
|
+
|
|
81
|
+
## 平台支持
|
|
82
|
+
|
|
83
|
+
| 平台 | 入口规则 | Skills 目录 | Hook 类型 | MCP 配置文件 |
|
|
84
|
+
|------|---------|------------|----------|-------------|
|
|
85
|
+
| Cursor | `.cursor/rules/dream-wf.mdc` | `.cursor/skills/` | `preToolUse` (python) | `.cursor/mcp.json` |
|
|
86
|
+
| Claude Code | `CLAUDE.md` | `.claude/skills/` | `PreToolUse` (python) | `.mcp.json` |
|
|
87
|
+
| OpenCode | `AGENTS.md` | `.opencode/skills/` | `tool.execute.before` plugin (js) | `opencode.json` |
|
|
88
|
+
| Codex | `AGENTS.md` | `.codex/skills/` | `PreToolUse` (python, hooks.json) | `.codex/config.toml` |
|
|
89
|
+
|
|
90
|
+
## Trellis
|
|
42
91
|
|
|
43
92
|
来源:https://github.com/mindfold-ai/trellis
|
|
44
93
|
|
|
@@ -49,12 +98,13 @@ npm install -g @mindfoldhq/trellis@latest
|
|
|
49
98
|
先初始化 Trellis,或者让 `dream-wf` 输出对应的初始化命令:
|
|
50
99
|
|
|
51
100
|
```bash
|
|
52
|
-
trellis init -u your-name --cursor
|
|
53
|
-
trellis init -u your-name --claude
|
|
54
|
-
trellis init -u your-name --opencode
|
|
101
|
+
trellis init -u your-name --cursor --yes
|
|
102
|
+
trellis init -u your-name --claude --yes
|
|
103
|
+
trellis init -u your-name --opencode --yes
|
|
104
|
+
trellis init -u your-name --codex --yes
|
|
55
105
|
```
|
|
56
106
|
|
|
57
|
-
## Grill Me
|
|
107
|
+
## Grill Me
|
|
58
108
|
|
|
59
109
|
来源:https://github.com/mattpocock/skills/blob/main/skills/productivity/grill-me/SKILL.md
|
|
60
110
|
|
|
@@ -119,8 +169,6 @@ MCP server 配置示例:
|
|
|
119
169
|
}
|
|
120
170
|
```
|
|
121
171
|
|
|
122
|
-
不要把真实 API key、token 或 MCP secret 提交到项目文件中。
|
|
123
|
-
|
|
124
172
|
## 生成文件
|
|
125
173
|
|
|
126
174
|
Cursor:
|
|
@@ -130,6 +178,7 @@ Cursor:
|
|
|
130
178
|
- `.cursor/skills/dream-wf-mcp-policy/SKILL.md`
|
|
131
179
|
- `.cursor/hooks/dream-wf-guard.py`
|
|
132
180
|
- `.cursor/hooks.json`
|
|
181
|
+
- `.cursor/mcp.json`
|
|
133
182
|
|
|
134
183
|
Claude Code:
|
|
135
184
|
|
|
@@ -138,6 +187,7 @@ Claude Code:
|
|
|
138
187
|
- `.claude/skills/dream-wf-mcp-policy/SKILL.md`
|
|
139
188
|
- `.claude/hooks/dream-wf-guard.py`
|
|
140
189
|
- `.claude/settings.json`
|
|
190
|
+
- `.mcp.json`
|
|
141
191
|
|
|
142
192
|
OpenCode:
|
|
143
193
|
|
|
@@ -145,6 +195,16 @@ OpenCode:
|
|
|
145
195
|
- `.opencode/skills/dream-wf-grill-prd/SKILL.md`
|
|
146
196
|
- `.opencode/skills/dream-wf-mcp-policy/SKILL.md`
|
|
147
197
|
- `.opencode/plugins/dream-wf-guard.js`
|
|
198
|
+
- `opencode.json`
|
|
199
|
+
|
|
200
|
+
Codex:
|
|
201
|
+
|
|
202
|
+
- `AGENTS.md` dream-wf entry block
|
|
203
|
+
- `.codex/skills/dream-wf-grill-prd/SKILL.md`
|
|
204
|
+
- `.codex/skills/dream-wf-mcp-policy/SKILL.md`
|
|
205
|
+
- `.codex/hooks/dream-wf-guard.py`
|
|
206
|
+
- `.codex/hooks.json`
|
|
207
|
+
- `.codex/config.toml`(含 `[features] hooks = true` 和 `[mcp_servers.*]`)
|
|
148
208
|
|
|
149
209
|
Trellis:
|
|
150
210
|
|
|
@@ -173,6 +233,13 @@ status: confirmed
|
|
|
173
233
|
|
|
174
234
|
```bash
|
|
175
235
|
npx dream-wf doctor -p cursor
|
|
236
|
+
npx dream-wf doctor -p codex
|
|
176
237
|
```
|
|
177
238
|
|
|
178
|
-
|
|
239
|
+
doctor 会检查:
|
|
240
|
+
|
|
241
|
+
- 必需二进制(node、python3、trellis、uvx)
|
|
242
|
+
- Trellis 项目目录和 workflow.md
|
|
243
|
+
- 平台对应的规则、skills、hook 文件
|
|
244
|
+
- MCP 配置文件存在性和默认 MCP 条目完整性
|
|
245
|
+
- 项目文件中的密钥泄露扫描
|
package/core/grill-prd-policy.md
CHANGED
|
@@ -12,6 +12,7 @@ Use grill-me behavior during Trellis planning. This replaces only the interview
|
|
|
12
12
|
- If a question can be answered by exploring the codebase, docs, config, existing specs, or task history, explore first instead of asking the user.
|
|
13
13
|
- After each answer, update `prd.md` immediately.
|
|
14
14
|
- Keep open questions explicit until they are answered or intentionally deferred.
|
|
15
|
+
- **Before requesting PRD confirmation, perform a Knowledge Verification pass.** Use `grok-search-mcp` (`web_search`, `web_fetch`) to verify technical assumptions that could be outdated or wrong. Record results in the `## Knowledge Verification` section of `prd.md`. Correct any outdated assumptions. Move unverified points to `Open Questions`. Add `knowledge verified` to the PRD after verification is complete.
|
|
15
16
|
- Do not start implementation until the PRD is reviewed and confirmed.
|
|
16
17
|
|
|
17
18
|
## Required PRD Sections
|
|
@@ -23,6 +24,7 @@ Use grill-me behavior during Trellis planning. This replaces only the interview
|
|
|
23
24
|
- Acceptance criteria
|
|
24
25
|
- Decisions
|
|
25
26
|
- Technical notes
|
|
27
|
+
- Knowledge verification
|
|
26
28
|
- Open questions
|
|
27
29
|
- Spec candidates
|
|
28
30
|
|
package/core/workflow-profile.md
CHANGED
|
@@ -24,6 +24,7 @@ Keep the native Trellis flow:
|
|
|
24
24
|
## Dream WF Patch Points
|
|
25
25
|
|
|
26
26
|
- Use `dream-wf-grill-prd` for PRD clarification instead of open-ended brainstorm interviewing.
|
|
27
|
+
- **Before PRD confirmation, perform a Knowledge Verification pass**: use `grok-search-mcp` (`web_search`, `web_fetch`) to verify technical assumptions that could be outdated or wrong. Record results in the `## Knowledge Verification` section of `prd.md`. Correct outdated assumptions. Add `knowledge verified` to the PRD after verification is complete.
|
|
27
28
|
- Generate initial spec candidates from user answers, PRD decisions, and verified project facts.
|
|
28
29
|
- Prefer `fast-context-mcp` for codebase semantic search.
|
|
29
30
|
- Prefer `grok-search-mcp` for external docs, live technical information, and webpage fetching.
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dream-wf",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Trellis workflow patch installer and MCP/skill aggregator for Cursor, Claude Code, OpenCode and Codex.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"dream-wf": "bin/dream-wf.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"check": "node --check bin/dream-wf.js && node --check src/cli/index.js && node --check src/lib/files.js && node --check src/lib/platforms.js && node --check src/lib/trellis.js && node --check src/lib/json.js && node --check src/doctor/index.js && node --check src/deps/index.js && node --check src/platforms/shared.js && node --check src/platforms/cursor/index.js && node --check src/platforms/claude-code/index.js && node --check src/platforms/opencode/index.js && node --check templates/hooks/opencode/dream-wf-guard.js"
|
|
10
|
+
"check": "node --check bin/dream-wf.js && node --check src/cli/index.js && node --check src/lib/files.js && node --check src/lib/platforms.js && node --check src/lib/trellis.js && node --check src/lib/json.js && node --check src/lib/catalog.js && node --check src/lib/mcp.js && node --check src/doctor/index.js && node --check src/deps/index.js && node --check src/platforms/shared.js && node --check src/platforms/cursor/index.js && node --check src/platforms/claude-code/index.js && node --check src/platforms/opencode/index.js && node --check src/platforms/codex/index.js && node --check src/tui/index.js && node --check templates/hooks/opencode/dream-wf-guard.js"
|
|
11
11
|
},
|
|
12
12
|
"keywords": [
|
|
13
13
|
"trellis",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"cursor",
|
|
16
16
|
"claude",
|
|
17
17
|
"opencode",
|
|
18
|
+
"codex",
|
|
18
19
|
"mcp"
|
|
19
20
|
],
|
|
20
21
|
"license": "MIT",
|
package/src/cli/index.js
CHANGED
|
@@ -1,91 +1,157 @@
|
|
|
1
|
-
import process from
|
|
2
|
-
import path from
|
|
3
|
-
import { fileURLToPath } from
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import {
|
|
5
|
+
assertSupportedPlatform,
|
|
6
|
+
normalizePlatform,
|
|
7
|
+
} from "../lib/platforms.js";
|
|
8
|
+
import {
|
|
9
|
+
ensureTrellisInitialized,
|
|
10
|
+
installTrellisProfile,
|
|
11
|
+
} from "../lib/trellis.js";
|
|
12
|
+
import { formatRelative } from "../lib/files.js";
|
|
13
|
+
import {
|
|
14
|
+
resolveSkills,
|
|
15
|
+
resolveMcps,
|
|
16
|
+
defaultSkillIds,
|
|
17
|
+
defaultMcpIds,
|
|
18
|
+
} from "../lib/catalog.js";
|
|
19
|
+
import { installCursor } from "../platforms/cursor/index.js";
|
|
20
|
+
import { installClaudeCode } from "../platforms/claude-code/index.js";
|
|
21
|
+
import { installOpenCode } from "../platforms/opencode/index.js";
|
|
22
|
+
import { installCodex } from "../platforms/codex/index.js";
|
|
23
|
+
import { runDoctor, formatDoctorReport } from "../doctor/index.js";
|
|
24
|
+
import { runInteractive } from "../tui/index.js";
|
|
25
|
+
|
|
26
|
+
const packageRoot = path.resolve(
|
|
27
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
28
|
+
"..",
|
|
29
|
+
"..",
|
|
30
|
+
);
|
|
13
31
|
|
|
14
32
|
export async function run(argv) {
|
|
33
|
+
// 无参数或仅 --help 以外无 subcommand 时,进入交互式 TUI。
|
|
34
|
+
if (argv.length === 0) {
|
|
35
|
+
const interactive = await runInteractive();
|
|
36
|
+
if (!interactive) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
await init(process.cwd(), interactive);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 优先处理全局 help 标志,避免被当作 command 或要求 -p。
|
|
44
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
45
|
+
writeOutput(helpText());
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
15
49
|
const { command, options } = parseArgs(argv);
|
|
16
50
|
|
|
17
|
-
if (
|
|
51
|
+
if (!command || command === "help") {
|
|
18
52
|
writeOutput(helpText());
|
|
19
53
|
return;
|
|
20
54
|
}
|
|
21
55
|
|
|
22
|
-
if (
|
|
23
|
-
|
|
56
|
+
if (command === "interactive" || command === "tui") {
|
|
57
|
+
const interactive = await runInteractive();
|
|
58
|
+
if (!interactive) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
await init(process.cwd(), interactive);
|
|
62
|
+
return;
|
|
24
63
|
}
|
|
25
64
|
|
|
26
65
|
const platform = normalizePlatform(options.platform);
|
|
27
66
|
assertSupportedPlatform(platform);
|
|
28
67
|
|
|
29
68
|
const rootDir = process.cwd();
|
|
30
|
-
const mode = options.mode ??
|
|
31
|
-
if (![
|
|
32
|
-
throw new Error(
|
|
69
|
+
const mode = options.mode ?? "strict";
|
|
70
|
+
if (!["strict", "advisory"].includes(mode)) {
|
|
71
|
+
throw new Error("Invalid --mode. Use strict or advisory.");
|
|
33
72
|
}
|
|
34
73
|
|
|
35
|
-
if (command ===
|
|
74
|
+
if (command === "init") {
|
|
36
75
|
await init(rootDir, { ...options, platform, mode });
|
|
37
76
|
return;
|
|
38
77
|
}
|
|
39
78
|
|
|
40
|
-
if (command ===
|
|
79
|
+
if (command === "doctor") {
|
|
41
80
|
const report = await runDoctor(rootDir, platform);
|
|
42
81
|
writeOutput(formatDoctorReport(report));
|
|
43
82
|
return;
|
|
44
83
|
}
|
|
45
84
|
|
|
46
|
-
if (command ===
|
|
85
|
+
if (command === "update") {
|
|
47
86
|
await init(rootDir, { ...options, platform, mode });
|
|
48
87
|
return;
|
|
49
88
|
}
|
|
50
89
|
|
|
51
|
-
if (command ===
|
|
52
|
-
throw new Error(
|
|
90
|
+
if (command === "uninstall") {
|
|
91
|
+
throw new Error(
|
|
92
|
+
"uninstall is planned but not implemented in this MVP. Remove dream-wf generated files manually if needed.",
|
|
93
|
+
);
|
|
53
94
|
}
|
|
54
95
|
|
|
55
96
|
throw new Error(`Unknown command "${command}".\n\n${helpText()}`);
|
|
56
97
|
}
|
|
57
98
|
|
|
58
99
|
async function init(rootDir, options) {
|
|
100
|
+
// 来自 TUI 的 options 已带 skills/mcps;来自 CLI 的 options 需要解析。
|
|
101
|
+
const platform = options.platform;
|
|
102
|
+
const mode = options.mode ?? "strict";
|
|
103
|
+
|
|
104
|
+
const skillIds = options.skillIds ?? defaultSkillIds();
|
|
105
|
+
const mcpIds = options.mcpIds ?? defaultMcpIds();
|
|
106
|
+
const skills = resolveSkills(
|
|
107
|
+
options.skills ? options.skills.map((s) => s.id) : skillIds,
|
|
108
|
+
);
|
|
109
|
+
const mcps = resolveMcps(
|
|
110
|
+
options.mcps ? options.mcps.map((m) => m.id) : mcpIds,
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const initOptions = { ...options, platform, mode, skills, mcps };
|
|
114
|
+
|
|
59
115
|
writeOutput(formatBanner());
|
|
60
116
|
|
|
61
117
|
const results = [];
|
|
62
|
-
const trellis = await ensureTrellisInitialized(rootDir,
|
|
118
|
+
const trellis = await ensureTrellisInitialized(rootDir, initOptions);
|
|
63
119
|
|
|
64
120
|
if (!trellis.initialized) {
|
|
65
|
-
writeOutput(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
121
|
+
writeOutput(
|
|
122
|
+
[
|
|
123
|
+
"Trellis is not initialized in this project.",
|
|
124
|
+
`Run: ${trellis.initCommand}`,
|
|
125
|
+
"Then rerun dream-wf init.",
|
|
126
|
+
].join("\n"),
|
|
127
|
+
);
|
|
70
128
|
return;
|
|
71
129
|
}
|
|
72
130
|
|
|
73
131
|
results.push(await installTrellisProfile(rootDir));
|
|
74
132
|
|
|
75
|
-
if (
|
|
76
|
-
results.push(...await installCursor(packageRoot, rootDir,
|
|
133
|
+
if (platform === "cursor") {
|
|
134
|
+
results.push(...(await installCursor(packageRoot, rootDir, initOptions)));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (platform === "claude") {
|
|
138
|
+
results.push(
|
|
139
|
+
...(await installClaudeCode(packageRoot, rootDir, initOptions)),
|
|
140
|
+
);
|
|
77
141
|
}
|
|
78
142
|
|
|
79
|
-
if (
|
|
80
|
-
results.push(...await
|
|
143
|
+
if (platform === "opencode") {
|
|
144
|
+
results.push(...(await installOpenCode(packageRoot, rootDir, initOptions)));
|
|
81
145
|
}
|
|
82
146
|
|
|
83
|
-
if (
|
|
84
|
-
results.push(...await
|
|
147
|
+
if (platform === "codex") {
|
|
148
|
+
results.push(...(await installCodex(packageRoot, rootDir, initOptions)));
|
|
85
149
|
}
|
|
86
150
|
|
|
87
|
-
const report = await runDoctor(rootDir,
|
|
88
|
-
writeOutput(
|
|
151
|
+
const report = await runDoctor(rootDir, platform);
|
|
152
|
+
writeOutput(
|
|
153
|
+
`${formatInstallReport(rootDir, results)}\n\n${formatDoctorReport(report)}`,
|
|
154
|
+
);
|
|
89
155
|
}
|
|
90
156
|
|
|
91
157
|
function parseArgs(argv) {
|
|
@@ -95,55 +161,85 @@ function parseArgs(argv) {
|
|
|
95
161
|
for (let index = 0; index < rest.length; index += 1) {
|
|
96
162
|
const arg = rest[index];
|
|
97
163
|
|
|
98
|
-
if (arg ===
|
|
164
|
+
if (arg === "--help" || arg === "-h") {
|
|
99
165
|
options.help = true;
|
|
100
166
|
continue;
|
|
101
167
|
}
|
|
102
168
|
|
|
103
|
-
if (arg ===
|
|
169
|
+
if (arg === "--install-deps") {
|
|
104
170
|
options.installDeps = true;
|
|
105
171
|
continue;
|
|
106
172
|
}
|
|
107
173
|
|
|
108
|
-
if (arg ===
|
|
174
|
+
if (arg === "--skip-deps") {
|
|
109
175
|
options.installDeps = false;
|
|
110
176
|
continue;
|
|
111
177
|
}
|
|
112
178
|
|
|
113
|
-
if (arg ===
|
|
179
|
+
if (arg === "--yes" || arg === "-y") {
|
|
114
180
|
options.yes = true;
|
|
115
181
|
continue;
|
|
116
182
|
}
|
|
117
183
|
|
|
118
|
-
if (arg ===
|
|
184
|
+
if (arg === "--skip-skills") {
|
|
185
|
+
options.skillIds = [];
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (arg === "--skip-mcps") {
|
|
190
|
+
options.mcpIds = [];
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (arg === "-p") {
|
|
119
195
|
const value = rest[index + 1];
|
|
120
|
-
if (!value || value.startsWith(
|
|
121
|
-
throw new Error(
|
|
196
|
+
if (!value || value.startsWith("-")) {
|
|
197
|
+
throw new Error(
|
|
198
|
+
"Missing value for -p. Use -p <cursor|claude|opencode|codex>.",
|
|
199
|
+
);
|
|
122
200
|
}
|
|
123
201
|
options.platform = value;
|
|
124
202
|
index += 1;
|
|
125
203
|
continue;
|
|
126
204
|
}
|
|
127
205
|
|
|
128
|
-
if (arg ===
|
|
206
|
+
if (arg === "--mode") {
|
|
129
207
|
options.mode = readOptionValue(arg, rest, index);
|
|
130
208
|
index += 1;
|
|
131
209
|
continue;
|
|
132
210
|
}
|
|
133
211
|
|
|
134
|
-
if (arg.startsWith(
|
|
135
|
-
options.mode = arg.slice(
|
|
212
|
+
if (arg.startsWith("--mode=")) {
|
|
213
|
+
options.mode = arg.slice("--mode=".length);
|
|
136
214
|
continue;
|
|
137
215
|
}
|
|
138
216
|
|
|
139
|
-
if (arg ===
|
|
217
|
+
if (arg === "--developer") {
|
|
140
218
|
options.developer = readOptionValue(arg, rest, index);
|
|
141
219
|
index += 1;
|
|
142
220
|
continue;
|
|
143
221
|
}
|
|
144
222
|
|
|
145
|
-
if (arg.startsWith(
|
|
146
|
-
options.developer = arg.slice(
|
|
223
|
+
if (arg.startsWith("--developer=")) {
|
|
224
|
+
options.developer = arg.slice("--developer=".length);
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (arg === "--skills") {
|
|
229
|
+
options.skillIds = readOptionValue(arg, rest, index)
|
|
230
|
+
.split(",")
|
|
231
|
+
.map((s) => s.trim())
|
|
232
|
+
.filter(Boolean);
|
|
233
|
+
index += 1;
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (arg === "--mcps") {
|
|
238
|
+
options.mcpIds = readOptionValue(arg, rest, index)
|
|
239
|
+
.split(",")
|
|
240
|
+
.map((s) => s.trim())
|
|
241
|
+
.filter(Boolean);
|
|
242
|
+
index += 1;
|
|
147
243
|
continue;
|
|
148
244
|
}
|
|
149
245
|
|
|
@@ -155,19 +251,21 @@ function parseArgs(argv) {
|
|
|
155
251
|
|
|
156
252
|
function readOptionValue(arg, rest, index) {
|
|
157
253
|
const value = rest[index + 1];
|
|
158
|
-
if (!value || value.startsWith(
|
|
254
|
+
if (!value || value.startsWith("-")) {
|
|
159
255
|
throw new Error(`Missing value for ${arg}.`);
|
|
160
256
|
}
|
|
161
257
|
return value;
|
|
162
258
|
}
|
|
163
259
|
|
|
164
260
|
function formatInstallReport(rootDir, results) {
|
|
165
|
-
const lines = [
|
|
261
|
+
const lines = ["dream-wf install report:"];
|
|
166
262
|
for (const result of results.flat().filter(Boolean)) {
|
|
167
|
-
const suffix = result.reason ? ` (${result.reason})` :
|
|
168
|
-
lines.push(
|
|
263
|
+
const suffix = result.reason ? ` (${result.reason})` : "";
|
|
264
|
+
lines.push(
|
|
265
|
+
`- ${result.action}: ${formatRelative(rootDir, result.path)}${suffix}`,
|
|
266
|
+
);
|
|
169
267
|
}
|
|
170
|
-
return lines.join(
|
|
268
|
+
return lines.join("\n");
|
|
171
269
|
}
|
|
172
270
|
|
|
173
271
|
function writeOutput(message) {
|
|
@@ -176,15 +274,14 @@ function writeOutput(message) {
|
|
|
176
274
|
|
|
177
275
|
function formatBanner() {
|
|
178
276
|
const banner = [
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
].join('\n');
|
|
277
|
+
"███████╗ ███████╗ ███████╗ ███████╗ ███╗ ███╗",
|
|
278
|
+
"██╔═══██╗ ██╔═══██╗ ██╔═════╝ ██╔═══██╗ ████╗ ████║",
|
|
279
|
+
"██║ ██║██████╔═╝ ███████╗ ███████╔╝ ██╔████╔██║",
|
|
280
|
+
"██║ ██║██╔═══██╗ ██╔════╝ ██╔═══██╗ ██║╚██╔╝██║",
|
|
281
|
+
"███████╔╝ ██║ ██║ ███████╗ ██║ ██║ ██║ ╚═╝ ██║",
|
|
282
|
+
"╚══════╝ ╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝",
|
|
283
|
+
" Dream WorkFlow v0.1.3",
|
|
284
|
+
].join("\n");
|
|
188
285
|
|
|
189
286
|
if (!process.stdout.isTTY || process.env.NO_COLOR) {
|
|
190
287
|
return banner;
|
|
@@ -194,5 +291,35 @@ function formatBanner() {
|
|
|
194
291
|
}
|
|
195
292
|
|
|
196
293
|
function helpText() {
|
|
197
|
-
return
|
|
294
|
+
return [
|
|
295
|
+
"dream-wf v0.1.3 · Trellis workflow 安装聚合器",
|
|
296
|
+
"",
|
|
297
|
+
"Usage:",
|
|
298
|
+
" dream-wf # 交互式 TUI(推荐)",
|
|
299
|
+
" dream-wf interactive # 同上",
|
|
300
|
+
" dream-wf init -p <cursor|claude|opencode|codex> [options]",
|
|
301
|
+
" dream-wf doctor -p <cursor|claude|opencode|codex>",
|
|
302
|
+
" dream-wf update -p <cursor|claude|opencode|codex>",
|
|
303
|
+
"",
|
|
304
|
+
"Options:",
|
|
305
|
+
" -p <platform> cursor|claude|opencode|codex",
|
|
306
|
+
" --mode strict|advisory 默认 strict",
|
|
307
|
+
" --skills <id,id,...> 指定要安装的 skill id(默认全部)",
|
|
308
|
+
" --mcps <id,id,...> 指定要配置的 mcp id(默认全部)",
|
|
309
|
+
" --skip-skills 不安装任何 skill",
|
|
310
|
+
" --skip-mcps 不配置任何 mcp",
|
|
311
|
+
" --install-deps --developer <n> 自动初始化 Trellis",
|
|
312
|
+
"",
|
|
313
|
+
"Skill ids:",
|
|
314
|
+
" trellis-dream-wf-patch, dream-wf-mcp-policy",
|
|
315
|
+
"",
|
|
316
|
+
"MCP ids:",
|
|
317
|
+
" fast-context, grok-search",
|
|
318
|
+
"",
|
|
319
|
+
"Examples:",
|
|
320
|
+
" npx dream-wf",
|
|
321
|
+
" npx dream-wf init -p cursor",
|
|
322
|
+
" npx dream-wf init -p claude --skills trellis-dream-wf-patch --mcps fast-context",
|
|
323
|
+
" npx dream-wf doctor -p codex",
|
|
324
|
+
].join("\n");
|
|
198
325
|
}
|