qwen-seed 1.0.0 → 1.0.2

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/bin/install.js CHANGED
@@ -3,6 +3,7 @@
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
5
  const os = require('os');
6
+ const readline = require('readline');
6
7
 
7
8
  // Colors
8
9
  const green = '\x1b[32m';
@@ -11,32 +12,30 @@ const yellow = '\x1b[33m';
11
12
  const dim = '\x1b[2m';
12
13
  const reset = '\x1b[0m';
13
14
 
14
- // Get version from package.json
15
15
  const pkg = require('../package.json');
16
16
 
17
17
  const banner = `
18
18
  ${green} \u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557
19
- \u2588\u2588\u2554\u2550\u2550\u2550\u255d\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255d\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
20
- \u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551
21
- \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255d \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551
22
- \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255d\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551
23
- \u255a\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u255d \u255a\u2550\u255d\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u255d\u255a\u2550\u2550\u2550\u2550\u2550\u255d${reset}
19
+ \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255d
20
+ \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557
21
+ \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255d
22
+ \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255d\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
23
+ \u255a\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\u255a\u2550\u2550\u2550\u2550\u2550\u255d${reset}
24
24
 
25
25
  SEED ${dim}v${pkg.version}${reset}
26
26
  Structured Evaluation & Engineering Design
27
27
  for Qwen Code
28
28
  `;
29
29
 
30
- // Parse args
31
30
  const args = process.argv.slice(2);
32
- const hasHelp = args.includes('--help') || args.includes('-h');
31
+ const hasGlobal = args.includes('--global') || args.includes('-g');
33
32
  const hasLocal = args.includes('--local') || args.includes('-l');
33
+ const hasHelp = args.includes('--help') || args.includes('-h');
34
34
 
35
- // Parse --config-dir argument
36
35
  function parseConfigDirArg() {
37
- const idx = args.findIndex(arg => arg === '--config-dir' || arg === '-c');
38
- if (idx !== -1) {
39
- const nextArg = args[idx + 1];
36
+ const configDirIndex = args.findIndex(arg => arg === '--config-dir' || arg === '-c');
37
+ if (configDirIndex !== -1) {
38
+ const nextArg = args[configDirIndex + 1];
40
39
  if (!nextArg || nextArg.startsWith('-')) {
41
40
  console.error(` ${yellow}--config-dir requires a path argument${reset}`);
42
41
  process.exit(1);
@@ -44,25 +43,17 @@ function parseConfigDirArg() {
44
43
  return nextArg;
45
44
  }
46
45
  const configDirArg = args.find(arg => arg.startsWith('--config-dir=') || arg.startsWith('-c='));
47
- if (configDirArg) {
48
- return configDirArg.split('=')[1];
49
- }
46
+ if (configDirArg) return configDirArg.split('=')[1];
50
47
  return null;
51
48
  }
52
49
 
53
- /**
54
- * Expand ~ to home directory
55
- */
50
+ const explicitConfigDir = parseConfigDirArg();
51
+
56
52
  function expandTilde(filePath) {
57
- if (filePath && filePath.startsWith('~/')) {
58
- return path.join(os.homedir(), filePath.slice(2));
59
- }
53
+ if (filePath && filePath.startsWith('~/')) return path.join(os.homedir(), filePath.slice(2));
60
54
  return filePath;
61
55
  }
62
56
 
63
- /**
64
- * Recursively copy directory, skipping .paul/, .git/, node_modules/, bin/
65
- */
66
57
  function copyDir(srcDir, destDir, skipDirs = []) {
67
58
  fs.mkdirSync(destDir, { recursive: true });
68
59
  const entries = fs.readdirSync(srcDir, { withFileTypes: true });
@@ -70,45 +61,36 @@ function copyDir(srcDir, destDir, skipDirs = []) {
70
61
  if (skipDirs.includes(entry.name)) continue;
71
62
  const srcPath = path.join(srcDir, entry.name);
72
63
  const destPath = path.join(destDir, entry.name);
73
- if (entry.isDirectory()) {
74
- copyDir(srcPath, destPath, skipDirs);
75
- } else {
76
- fs.copyFileSync(srcPath, destPath);
77
- }
64
+ if (entry.isDirectory()) copyDir(srcPath, destPath, skipDirs);
65
+ else fs.copyFileSync(srcPath, destPath);
78
66
  }
79
67
  }
80
68
 
81
- /**
82
- * Count files recursively
83
- */
84
69
  function countFiles(dir, ext) {
85
70
  let count = 0;
86
71
  const entries = fs.readdirSync(dir, { withFileTypes: true });
87
72
  for (const entry of entries) {
88
73
  const fullPath = path.join(dir, entry.name);
89
- if (entry.isDirectory()) {
90
- count += countFiles(fullPath, ext);
91
- } else if (!ext || entry.name.endsWith(ext)) {
92
- count++;
93
- }
74
+ if (entry.isDirectory()) count += countFiles(fullPath, ext);
75
+ else if (!ext || entry.name.endsWith(ext)) count++;
94
76
  }
95
77
  return count;
96
78
  }
97
79
 
98
80
  console.log(banner);
99
81
 
100
- // Show help
101
82
  if (hasHelp) {
102
83
  console.log(` ${yellow}Usage:${reset} npx qwen-seed [options]
103
84
 
104
85
  ${yellow}Options:${reset}
105
- ${cyan}-l, --local${reset} Install to ./.qwen/commands/ instead of global
106
- ${cyan}-c, --config-dir <path>${reset} Specify custom Qwen config directory
107
- ${cyan}-h, --help${reset} Show this help message
86
+ ${cyan}-g, --global${reset} Install globally (to Qwen config directory)
87
+ ${cyan}-l, --local${reset} Install locally (to ./.qwen/ in current directory)
88
+ ${cyan}-c, --config-dir <path>${reset} Specify custom Qwen config directory
89
+ ${cyan}-h, --help${reset} Show this help message
108
90
 
109
91
  ${yellow}Examples:${reset}
110
- ${dim}# Install globally (default) — available in all workspaces${reset}
111
- npx qwen-seed
92
+ ${dim}# Install globally (recommended)${reset}
93
+ npx qwen-seed --global
112
94
 
113
95
  ${dim}# Install to current project only${reset}
114
96
  npx qwen-seed --local
@@ -116,70 +98,93 @@ if (hasHelp) {
116
98
  ${yellow}What gets installed:${reset}
117
99
  ${cyan}commands/qwen-seed/${reset}
118
100
  seed.md Entry point (routing + persona)
119
- tasks/ 5 task files (ideate, graduate, launch, status, add-type)
120
- data/ 15 type-specific data files (5 types x 3 files)
101
+ tasks/ 5 task files
102
+ data/ 15 type-specific data files
121
103
  templates/ 5 PLANNING.md output templates
122
104
  checklists/ Planning quality gate
123
105
  `);
124
106
  process.exit(0);
125
107
  }
126
108
 
127
- // Determine install target
128
- const explicitConfigDir = parseConfigDirArg();
129
- const configDir = expandTilde(explicitConfigDir) || expandTilde(process.env.QWEN_CONFIG_DIR);
130
- const globalDir = configDir || path.join(os.homedir(), '.qwen');
131
- const qwenDir = hasLocal ? path.join(process.cwd(), '.qwen') : globalDir;
132
- const seedDest = path.join(qwenDir, 'commands', 'qwen-seed');
133
-
134
- const locationLabel = hasLocal
135
- ? seedDest.replace(process.cwd(), '.')
136
- : seedDest.replace(os.homedir(), '~');
137
-
138
- // Check if already installed
139
- if (fs.existsSync(seedDest)) {
140
- console.log(` ${yellow}Existing installation found at ${locationLabel}${reset}`);
141
- console.log(` Updating...`);
142
- fs.rmSync(seedDest, { recursive: true, force: true });
143
- }
109
+ function install(isGlobal) {
110
+ const src = path.join(__dirname, '..');
111
+ const configDir = expandTilde(explicitConfigDir) || expandTilde(process.env.QWEN_CONFIG_DIR);
112
+ const globalDir = configDir || path.join(os.homedir(), '.qwen');
113
+ const qwenDir = isGlobal ? globalDir : path.join(process.cwd(), '.qwen');
114
+ const seedDest = path.join(qwenDir, 'commands', 'qwen-seed');
115
+
116
+ const locationLabel = isGlobal
117
+ ? seedDest.replace(os.homedir(), '~')
118
+ : seedDest.replace(process.cwd(), '.');
119
+
120
+ if (fs.existsSync(seedDest)) {
121
+ console.log(` ${yellow}Existing installation found at ${locationLabel}${reset}`);
122
+ console.log(` Updating...`);
123
+ fs.rmSync(seedDest, { recursive: true, force: true });
124
+ }
125
+
126
+ console.log(` Installing to ${cyan}${locationLabel}${reset}\n`);
127
+
128
+ fs.mkdirSync(seedDest, { recursive: true });
129
+ fs.copyFileSync(path.join(src, 'seed.md'), path.join(seedDest, 'seed.md'));
130
+ console.log(` ${green}+${reset} seed.md ${dim}(entry point)${reset}`);
131
+
132
+ const tasksSrc = path.join(src, 'tasks');
133
+ const tasksDest = path.join(seedDest, 'tasks');
134
+ copyDir(tasksSrc, tasksDest);
135
+ console.log(` ${green}+${reset} tasks/ ${dim}(${countFiles(tasksSrc, '.md')} task files)${reset}`);
144
136
 
145
- console.log(` Installing to ${cyan}${locationLabel}${reset}\n`);
146
-
147
- // Copy skill files
148
- const src = path.join(__dirname, '..');
149
-
150
- // Copy entry point
151
- fs.mkdirSync(seedDest, { recursive: true });
152
- fs.copyFileSync(path.join(src, 'seed.md'), path.join(seedDest, 'seed.md'));
153
- console.log(` ${green}+${reset} seed.md ${dim}(entry point)${reset}`);
154
-
155
- // Copy tasks
156
- const tasksSrc = path.join(src, 'tasks');
157
- const tasksDest = path.join(seedDest, 'tasks');
158
- copyDir(tasksSrc, tasksDest);
159
- const taskCount = countFiles(tasksSrc, '.md');
160
- console.log(` ${green}+${reset} tasks/ ${dim}(${taskCount} task files)${reset}`);
161
-
162
- // Copy data
163
- const dataSrc = path.join(src, 'data');
164
- const dataDest = path.join(seedDest, 'data');
165
- copyDir(dataSrc, dataDest);
166
- const dataCount = countFiles(dataSrc, '.md');
167
- const typeCount = fs.readdirSync(dataSrc, { withFileTypes: true }).filter(e => e.isDirectory()).length;
168
- console.log(` ${green}+${reset} data/ ${dim}(${typeCount} types, ${dataCount} files)${reset}`);
169
-
170
- // Copy templates
171
- const templatesSrc = path.join(src, 'templates');
172
- const templatesDest = path.join(seedDest, 'templates');
173
- copyDir(templatesSrc, templatesDest);
174
- const templateCount = countFiles(templatesSrc, '.md');
175
- console.log(` ${green}+${reset} templates/ ${dim}(${templateCount} planning templates)${reset}`);
176
-
177
- // Copy checklists
178
- const checklistsSrc = path.join(src, 'checklists');
179
- const checklistsDest = path.join(seedDest, 'checklists');
180
- copyDir(checklistsSrc, checklistsDest);
181
- console.log(` ${green}+${reset} checklists/ ${dim}(planning quality gate)${reset}`);
182
-
183
- console.log(`
137
+ const dataSrc = path.join(src, 'data');
138
+ const dataDest = path.join(seedDest, 'data');
139
+ copyDir(dataSrc, dataDest);
140
+ const typeCount = fs.readdirSync(dataSrc, { withFileTypes: true }).filter(e => e.isDirectory()).length;
141
+ console.log(` ${green}+${reset} data/ ${dim}(${typeCount} types, ${countFiles(dataSrc, '.md')} files)${reset}`);
142
+
143
+ const templatesSrc = path.join(src, 'templates');
144
+ const templatesDest = path.join(seedDest, 'templates');
145
+ copyDir(templatesSrc, templatesDest);
146
+ console.log(` ${green}+${reset} templates/ ${dim}(${countFiles(templatesSrc, '.md')} templates)${reset}`);
147
+
148
+ const checklistsSrc = path.join(src, 'checklists');
149
+ const checklistsDest = path.join(seedDest, 'checklists');
150
+ copyDir(checklistsSrc, checklistsDest);
151
+ console.log(` ${green}+${reset} checklists/ ${dim}(planning quality gate)${reset}`);
152
+
153
+ console.log(`
184
154
  ${green}Done!${reset} Open Qwen Code and type ${cyan}/seed${reset} to start.
185
155
  `);
156
+ }
157
+
158
+ function promptLocation() {
159
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
160
+
161
+ const configDir = expandTilde(explicitConfigDir) || expandTilde(process.env.QWEN_CONFIG_DIR);
162
+ const globalPath = configDir || path.join(os.homedir(), '.qwen');
163
+ const globalLabel = globalPath.replace(os.homedir(), '~');
164
+
165
+ console.log(` ${yellow}Where would you like to install?${reset}
166
+
167
+ ${cyan}1${reset}) Global ${dim}(${globalLabel})${reset} - available in all projects
168
+ ${cyan}2${reset}) Local ${dim}(./.qwen)${reset} - this project only
169
+ `);
170
+
171
+ rl.question(` Choice ${dim}[1]${reset}: `, (answer) => {
172
+ rl.close();
173
+ const choice = answer.trim() || '1';
174
+ install(choice !== '2');
175
+ });
176
+ }
177
+
178
+ if (hasGlobal && hasLocal) {
179
+ console.error(` ${yellow}Cannot specify both --global and --local${reset}`);
180
+ process.exit(1);
181
+ } else if (explicitConfigDir && hasLocal) {
182
+ console.error(` ${yellow}Cannot use --config-dir with --local${reset}`);
183
+ process.exit(1);
184
+ } else if (hasGlobal) {
185
+ install(true);
186
+ } else if (hasLocal) {
187
+ install(false);
188
+ } else {
189
+ promptLocation();
190
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwen-seed",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Typed project incubator — guided ideation through graduation for Qwen Code",
5
5
  "bin": {
6
6
  "qwen-seed": "bin/install.js"
package/seed.md CHANGED
@@ -54,18 +54,18 @@ Project coach — helps shape raw ideas into structured, buildable plans.
54
54
  Nothing — SEED is lightweight until a command is invoked.
55
55
 
56
56
  ## Load on Command
57
- @{~/.qwen/commands/seed/tasks/ideate.md} (when user runs /seed or /seed ideate)
58
- @{~/.qwen/commands/seed/tasks/graduate.md} (when user runs /seed graduate)
59
- @{~/.qwen/commands/seed/tasks/launch.md} (when user runs /seed launch)
60
- @{~/.qwen/commands/seed/tasks/status.md} (when user runs /seed status)
61
- @{~/.qwen/commands/seed/tasks/add-type.md} (when user runs /seed add-type)
57
+ @{~/.qwen/commands/qwen-seed/tasks/ideate.md} (when user runs /seed or /seed ideate)
58
+ @{~/.qwen/commands/qwen-seed/tasks/graduate.md} (when user runs /seed graduate)
59
+ @{~/.qwen/commands/qwen-seed/tasks/launch.md} (when user runs /seed launch)
60
+ @{~/.qwen/commands/qwen-seed/tasks/status.md} (when user runs /seed status)
61
+ @{~/.qwen/commands/qwen-seed/tasks/add-type.md} (when user runs /seed add-type)
62
62
 
63
63
  ## Load on Demand
64
- @{~/.qwen/commands/seed/data/{type}/guide.md} (after type selection during ideation — conversation sections)
65
- @{~/.qwen/commands/seed/data/{type}/config.md} (after type selection — rigor level, demeanor, section requirements)
66
- @{~/.qwen/commands/seed/data/{type}/skill-loadout.md} (during skill loadout step — ecosystem tool recommendations)
67
- @{~/.qwen/commands/seed/templates/planning-{type}.md} (during PLANNING.md generation)
68
- @{~/.qwen/commands/seed/checklists/planning-quality.md} (before graduate/launch — quality gate)
64
+ @{~/.qwen/commands/qwen-seed/data/{type}/guide.md} (after type selection during ideation — conversation sections)
65
+ @{~/.qwen/commands/qwen-seed/data/{type}/config.md} (after type selection — rigor level, demeanor, section requirements)
66
+ @{~/.qwen/commands/qwen-seed/data/{type}/skill-loadout.md} (during skill loadout step — ecosystem tool recommendations)
67
+ @{~/.qwen/commands/qwen-seed/templates/planning-{type}.md} (during PLANNING.md generation)
68
+ @{~/.qwen/commands/qwen-seed/checklists/planning-quality.md} (before graduate/launch — quality gate)
69
69
  </routing>
70
70
 
71
71
  <greeting>
package/tasks/add-type.md CHANGED
@@ -13,9 +13,9 @@ As a builder with a project category SEED doesn't cover, I want to add a custom
13
13
  </when-to-use>
14
14
 
15
15
  <context>
16
- @{~/.qwen/commands/seed/data/application/guide.md} (reference for guide structure)
17
- @{~/.qwen/commands/seed/data/application/config.md} (reference for config structure)
18
- @{~/.qwen/commands/seed/data/application/skill-loadout.md} (reference for loadout structure)
16
+ @{~/.qwen/commands/qwen-seed/data/application/guide.md} (reference for guide structure)
17
+ @{~/.qwen/commands/qwen-seed/data/application/config.md} (reference for config structure)
18
+ @{~/.qwen/commands/qwen-seed/data/application/skill-loadout.md} (reference for loadout structure)
19
19
  </context>
20
20
 
21
21
  <steps>
package/tasks/graduate.md CHANGED
@@ -13,8 +13,8 @@ As a builder with a completed PLANNING.md, I want to graduate my project into a
13
13
  </when-to-use>
14
14
 
15
15
  <context>
16
- @{~/.qwen/commands/seed/seed.md}
17
- @{~/.qwen/commands/seed/checklists/planning-quality.md} (quality gate — loaded before graduation)
16
+ @{~/.qwen/commands/qwen-seed/seed.md}
17
+ @{~/.qwen/commands/qwen-seed/checklists/planning-quality.md} (quality gate — loaded before graduation)
18
18
  </context>
19
19
 
20
20
  <steps>
package/tasks/ideate.md CHANGED
@@ -14,12 +14,12 @@ As a builder with a raw idea, I want guided exploration shaped by my project typ
14
14
  </when-to-use>
15
15
 
16
16
  <context>
17
- @{~/.qwen/commands/seed/seed.md}
18
- @{~/.qwen/commands/seed/data/{type}/guide.md} (loaded after type selection)
19
- @{~/.qwen/commands/seed/data/{type}/config.md} (loaded after type selection)
20
- @{~/.qwen/commands/seed/data/{type}/skill-loadout.md} (loaded during skill loadout step)
21
- @{~/.qwen/commands/seed/templates/planning-{type}.md} (loaded during output generation)
22
- @{~/.qwen/commands/seed/checklists/planning-quality.md} (referenced as quality gate before output)
17
+ @{~/.qwen/commands/qwen-seed/seed.md}
18
+ @{~/.qwen/commands/qwen-seed/data/{type}/guide.md} (loaded after type selection)
19
+ @{~/.qwen/commands/qwen-seed/data/{type}/config.md} (loaded after type selection)
20
+ @{~/.qwen/commands/qwen-seed/data/{type}/skill-loadout.md} (loaded during skill loadout step)
21
+ @{~/.qwen/commands/qwen-seed/templates/planning-{type}.md} (loaded during output generation)
22
+ @{~/.qwen/commands/qwen-seed/checklists/planning-quality.md} (referenced as quality gate before output)
23
23
  </context>
24
24
 
25
25
  <steps>
package/tasks/launch.md CHANGED
@@ -13,8 +13,8 @@ As a builder ready to start building, I want to graduate my project and set up P
13
13
  </when-to-use>
14
14
 
15
15
  <context>
16
- @{~/.qwen/commands/seed/seed.md}
17
- @{~/.qwen/commands/seed/tasks/graduate.md} (delegation target — launch wraps this flow)
16
+ @{~/.qwen/commands/qwen-seed/seed.md}
17
+ @{~/.qwen/commands/qwen-seed/tasks/graduate.md} (delegation target — launch wraps this flow)
18
18
  </context>
19
19
 
20
20
  <steps>