iterate-skill-installer 2.4.1 → 2.4.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 +7 -5
- package/README.zh-CN.md +7 -5
- package/bin/cli.js +4 -75
- package/lib/installer.js +99 -3
- package/package.json +1 -1
- package/test/mode.test.js +16 -1
package/README.md
CHANGED
|
@@ -26,6 +26,9 @@ npx iterate-skill-installer --target ./my-project
|
|
|
26
26
|
|
|
27
27
|
# Force overwrite existing skill files
|
|
28
28
|
npx iterate-skill-installer --force
|
|
29
|
+
|
|
30
|
+
# Skill-only install — skip installing the iterate CLI
|
|
31
|
+
npx iterate-skill-installer --no-cli
|
|
29
32
|
```
|
|
30
33
|
|
|
31
34
|
## What it does
|
|
@@ -42,12 +45,11 @@ npx iterate-skill-installer --force
|
|
|
42
45
|
7. Installs the `iterate` CLI onto your PATH (prefers `pipx`, otherwise
|
|
43
46
|
`pip install --user`) so you can run `iterate onboard` directly.
|
|
44
47
|
|
|
45
|
-
> **Note:** the installer
|
|
48
|
+
> **Note:** the installer normally puts the `iterate` CLI on your PATH so a single
|
|
46
49
|
> command gives you both the skill and the CLI. If you **don't** want the CLI
|
|
47
|
-
> auto-installed,
|
|
48
|
-
> `
|
|
49
|
-
>
|
|
50
|
-
> still install it later with `pipx install .` or `pip install .` from a checkout.
|
|
50
|
+
> auto-installed, pass `--no-cli` to install the skill only — you can install the
|
|
51
|
+
> CLI later with `pipx install .` or `pip install .` from a checkout. If the CLI
|
|
52
|
+
> install fails, you can still install it later the same way.
|
|
51
53
|
|
|
52
54
|
## Supported AI assistants
|
|
53
55
|
|
package/README.zh-CN.md
CHANGED
|
@@ -26,6 +26,9 @@ npx iterate-skill-installer --target ./my-project
|
|
|
26
26
|
|
|
27
27
|
# 强制覆盖已有技能文件
|
|
28
28
|
npx iterate-skill-installer --force
|
|
29
|
+
|
|
30
|
+
# 仅安装技能 —— 跳过安装 iterate CLI
|
|
31
|
+
npx iterate-skill-installer --no-cli
|
|
29
32
|
```
|
|
30
33
|
|
|
31
34
|
## 它做了什么
|
|
@@ -42,11 +45,10 @@ npx iterate-skill-installer --force
|
|
|
42
45
|
7. 把 `iterate` CLI 安装到你的 PATH(优先 `pipx`,否则 `pip install --user`),
|
|
43
46
|
以便你直接运行 `iterate onboard`。
|
|
44
47
|
|
|
45
|
-
> **注意:**
|
|
46
|
-
> 得到技能和 CLI。如果**不**想自动安装 CLI
|
|
47
|
-
> `
|
|
48
|
-
>
|
|
49
|
-
> `pipx install .` 或 `pip install .` 补装。
|
|
48
|
+
> **注意:** 安装器通常会在你 PATH 上装好 `iterate` CLI,这样一条命令就能同时
|
|
49
|
+
> 得到技能和 CLI。如果**不**想自动安装 CLI,请加 `--no-cli` 只装技能——之后可从
|
|
50
|
+
> 检出目录用 `pipx install .` 或 `pip install .` 补装。如果 CLI 安装失败,你之后
|
|
51
|
+
> 也可用同样的方式补装。
|
|
50
52
|
|
|
51
53
|
## 支持的 AI 助手
|
|
52
54
|
|
package/bin/cli.js
CHANGED
|
@@ -10,87 +10,14 @@
|
|
|
10
10
|
* npx iterate-skill-installer --ai trae
|
|
11
11
|
* npx iterate-skill-installer --target /path/to/project
|
|
12
12
|
* npx iterate-skill-installer --global
|
|
13
|
+
* npx iterate-skill-installer --no-cli
|
|
13
14
|
*
|
|
14
15
|
* The installer downloads the latest GitHub release, verifies its SHA256
|
|
15
16
|
* checksum, then delegates file copying and assistant selection to the
|
|
16
17
|
* Python install script bundled in the release.
|
|
17
18
|
*/
|
|
18
19
|
|
|
19
|
-
const { main } = require('../lib/installer');
|
|
20
|
-
|
|
21
|
-
function parseArgs(argv) {
|
|
22
|
-
const options = {
|
|
23
|
-
global: true,
|
|
24
|
-
ai: null,
|
|
25
|
-
target: null,
|
|
26
|
-
force: false,
|
|
27
|
-
token: process.env.GITHUB_TOKEN || null,
|
|
28
|
-
// Track whether the user explicitly chose global/project mode so the
|
|
29
|
-
// installer can later ask about the current directory's project intent.
|
|
30
|
-
globalExplicit: false,
|
|
31
|
-
targetExplicit: false,
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
for (let i = 0; i < argv.length; i++) {
|
|
35
|
-
const arg = argv[i];
|
|
36
|
-
const next = argv[i + 1];
|
|
37
|
-
|
|
38
|
-
switch (arg) {
|
|
39
|
-
case '--ai':
|
|
40
|
-
if (!next) {
|
|
41
|
-
console.error('Error: --ai requires a value');
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
options.ai = next;
|
|
45
|
-
i++;
|
|
46
|
-
break;
|
|
47
|
-
case '--target':
|
|
48
|
-
if (!next) {
|
|
49
|
-
console.error('Error: --target requires a value');
|
|
50
|
-
process.exit(1);
|
|
51
|
-
}
|
|
52
|
-
options.target = next;
|
|
53
|
-
options.global = false;
|
|
54
|
-
options.targetExplicit = true;
|
|
55
|
-
i++;
|
|
56
|
-
break;
|
|
57
|
-
case '--global':
|
|
58
|
-
options.global = true;
|
|
59
|
-
options.target = null;
|
|
60
|
-
options.globalExplicit = true;
|
|
61
|
-
break;
|
|
62
|
-
case '--force':
|
|
63
|
-
options.force = true;
|
|
64
|
-
break;
|
|
65
|
-
case '--token':
|
|
66
|
-
if (!next) {
|
|
67
|
-
console.error('Error: --token requires a value');
|
|
68
|
-
process.exit(1);
|
|
69
|
-
}
|
|
70
|
-
options.token = next;
|
|
71
|
-
i++;
|
|
72
|
-
break;
|
|
73
|
-
case '-h':
|
|
74
|
-
case '--help':
|
|
75
|
-
printHelp();
|
|
76
|
-
process.exit(0);
|
|
77
|
-
break;
|
|
78
|
-
case '-v':
|
|
79
|
-
case '--version':
|
|
80
|
-
console.log(require('../package.json').version);
|
|
81
|
-
process.exit(0);
|
|
82
|
-
break;
|
|
83
|
-
default:
|
|
84
|
-
if (arg.startsWith('-')) {
|
|
85
|
-
console.error(`Error: unknown option ${arg}`);
|
|
86
|
-
process.exit(1);
|
|
87
|
-
}
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return options;
|
|
93
|
-
}
|
|
20
|
+
const { main, parseArgs } = require('../lib/installer');
|
|
94
21
|
|
|
95
22
|
function printHelp() {
|
|
96
23
|
console.log(`
|
|
@@ -101,6 +28,7 @@ Options:
|
|
|
101
28
|
--target <path> Install into a project directory instead of the global home dir.
|
|
102
29
|
--global Install into the user's home directory (default).
|
|
103
30
|
--force Overwrite existing skill files.
|
|
31
|
+
--no-cli Skip installing the iterate CLI (skill-only install).
|
|
104
32
|
--token <token> GitHub token for higher API rate limits.
|
|
105
33
|
-h, --help Show this help message.
|
|
106
34
|
-v, --version Show version.
|
|
@@ -109,6 +37,7 @@ Examples:
|
|
|
109
37
|
npx iterate-skill-installer
|
|
110
38
|
npx iterate-skill-installer --ai trae
|
|
111
39
|
npx iterate-skill-installer --target ./my-project
|
|
40
|
+
npx iterate-skill-installer --no-cli
|
|
112
41
|
`);
|
|
113
42
|
}
|
|
114
43
|
|
package/lib/installer.js
CHANGED
|
@@ -364,6 +364,84 @@ async function installRequirements(pythonBin, requirementsPath) {
|
|
|
364
364
|
await runCommand(pythonBin, ['-m', 'pip', 'install', '--quiet', '--requirement', requirementsPath]);
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Parse the installer's command-line arguments.
|
|
369
|
+
*
|
|
370
|
+
* Kept as a pure function (exported) so the flag surface — including the
|
|
371
|
+
* skill-only ``--no-cli`` switch — can be unit-tested without spawning the
|
|
372
|
+
* full download-and-install pipeline. ``process.exit`` is only reached for
|
|
373
|
+
* hard argument errors (e.g. a value-consuming flag missing its value).
|
|
374
|
+
*/
|
|
375
|
+
function parseArgs(argv) {
|
|
376
|
+
const options = {
|
|
377
|
+
global: true,
|
|
378
|
+
ai: null,
|
|
379
|
+
target: null,
|
|
380
|
+
force: false,
|
|
381
|
+
noCli: false,
|
|
382
|
+
token: process.env.GITHUB_TOKEN || null,
|
|
383
|
+
// Track whether the user explicitly chose global/project mode so the
|
|
384
|
+
// installer can later ask about the current directory's project intent.
|
|
385
|
+
globalExplicit: false,
|
|
386
|
+
targetExplicit: false,
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
for (let i = 0; i < argv.length; i++) {
|
|
390
|
+
const arg = argv[i];
|
|
391
|
+
const next = argv[i + 1];
|
|
392
|
+
|
|
393
|
+
switch (arg) {
|
|
394
|
+
case '--ai':
|
|
395
|
+
if (!next) {
|
|
396
|
+
console.error('Error: --ai requires a value');
|
|
397
|
+
process.exit(1);
|
|
398
|
+
}
|
|
399
|
+
options.ai = next;
|
|
400
|
+
i++;
|
|
401
|
+
break;
|
|
402
|
+
case '--target':
|
|
403
|
+
if (!next) {
|
|
404
|
+
console.error('Error: --target requires a value');
|
|
405
|
+
process.exit(1);
|
|
406
|
+
}
|
|
407
|
+
options.target = next;
|
|
408
|
+
options.global = false;
|
|
409
|
+
options.targetExplicit = true;
|
|
410
|
+
i++;
|
|
411
|
+
break;
|
|
412
|
+
case '--global':
|
|
413
|
+
options.global = true;
|
|
414
|
+
options.target = null;
|
|
415
|
+
options.globalExplicit = true;
|
|
416
|
+
break;
|
|
417
|
+
case '--force':
|
|
418
|
+
options.force = true;
|
|
419
|
+
break;
|
|
420
|
+
case '--no-cli':
|
|
421
|
+
// Skill-only install: skip the automated `iterate` CLI install so a
|
|
422
|
+
// user who only wants the skill is not surprised by a global install.
|
|
423
|
+
options.noCli = true;
|
|
424
|
+
break;
|
|
425
|
+
case '--token':
|
|
426
|
+
if (!next) {
|
|
427
|
+
console.error('Error: --token requires a value');
|
|
428
|
+
process.exit(1);
|
|
429
|
+
}
|
|
430
|
+
options.token = next;
|
|
431
|
+
i++;
|
|
432
|
+
break;
|
|
433
|
+
default:
|
|
434
|
+
if (arg.startsWith('-')) {
|
|
435
|
+
console.error(`Error: unknown option ${arg}`);
|
|
436
|
+
process.exit(1);
|
|
437
|
+
}
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
return options;
|
|
443
|
+
}
|
|
444
|
+
|
|
367
445
|
async function main(options = {}) {
|
|
368
446
|
printBanner();
|
|
369
447
|
|
|
@@ -372,7 +450,14 @@ async function main(options = {}) {
|
|
|
372
450
|
// whether that directory is the target project.
|
|
373
451
|
options = await resolveInstallMode(options);
|
|
374
452
|
|
|
375
|
-
const {
|
|
453
|
+
const {
|
|
454
|
+
global: globalInstall = true,
|
|
455
|
+
ai = null,
|
|
456
|
+
token = null,
|
|
457
|
+
target = null,
|
|
458
|
+
force = false,
|
|
459
|
+
noCli = false,
|
|
460
|
+
} = options;
|
|
376
461
|
|
|
377
462
|
step('Checking environment');
|
|
378
463
|
const pythonBin = await findPython();
|
|
@@ -495,8 +580,18 @@ async function main(options = {}) {
|
|
|
495
580
|
}
|
|
496
581
|
success('iterate-skill installation finished.');
|
|
497
582
|
|
|
498
|
-
|
|
499
|
-
|
|
583
|
+
if (noCli) {
|
|
584
|
+
// Skill-only install: explain how to add the CLI later instead of
|
|
585
|
+
// silently installing it globally.
|
|
586
|
+
hint('Skipped installing the iterate CLI (--no-cli).');
|
|
587
|
+
hint('Install it later for `iterate onboard` with: pipx install <repo> (or) pip install .');
|
|
588
|
+
} else {
|
|
589
|
+
// Install the iterate CLI so `iterate onboard` works right after
|
|
590
|
+
// install. Made explicit up front so skill-only users are not surprised
|
|
591
|
+
// by a global CLI install (skip with --no-cli).
|
|
592
|
+
step('Installing the iterate CLI (skip with --no-cli)');
|
|
593
|
+
await installCli(pythonBin, sourceDir);
|
|
594
|
+
}
|
|
500
595
|
|
|
501
596
|
frameSection('Done', [
|
|
502
597
|
`\x1b[32m✓\x1b[0m iterate-skill ${tag} installed`,
|
|
@@ -510,6 +605,7 @@ async function main(options = {}) {
|
|
|
510
605
|
|
|
511
606
|
module.exports = {
|
|
512
607
|
main,
|
|
608
|
+
parseArgs,
|
|
513
609
|
ITERATE_BANNER,
|
|
514
610
|
InstallerError,
|
|
515
611
|
resolveInstallMode,
|
package/package.json
CHANGED
package/test/mode.test.js
CHANGED
|
@@ -9,7 +9,7 @@ const assert = require('node:assert');
|
|
|
9
9
|
const fs = require('node:fs');
|
|
10
10
|
const path = require('node:path');
|
|
11
11
|
const os = require('node:os');
|
|
12
|
-
const { resolveInstallMode, parseChecksums } = require('../lib/installer');
|
|
12
|
+
const { resolveInstallMode, parseChecksums, parseArgs } = require('../lib/installer');
|
|
13
13
|
|
|
14
14
|
const originalCwd = process.cwd();
|
|
15
15
|
const originalHome = os.homedir;
|
|
@@ -97,6 +97,21 @@ async function run() {
|
|
|
97
97
|
assert.strictEqual(multi.get('b.txt'), 'bb');
|
|
98
98
|
|
|
99
99
|
console.log('mode.test.js: all parseChecksums tests passed');
|
|
100
|
+
|
|
101
|
+
// parseArgs: --no-cli must toggle skill-only mode, and default to off.
|
|
102
|
+
assert.strictEqual(parseArgs([]).noCli, false, 'noCli should default to false');
|
|
103
|
+
assert.strictEqual(parseArgs(['--no-cli']).noCli, true, '--no-cli should set noCli');
|
|
104
|
+
assert.strictEqual(parseArgs(['--no-cli', '--force', '--global']).noCli, true, 'noCli persists with other flags');
|
|
105
|
+
assert.strictEqual(parseArgs(['--global']).noCli, false, 'unrelated flags do not set noCli');
|
|
106
|
+
|
|
107
|
+
// parseArgs: unrelated flag surface is preserved (target/global/ai/force).
|
|
108
|
+
const combo = parseArgs(['--ai', 'trae', '--target', '/proj', '--force']);
|
|
109
|
+
assert.strictEqual(combo.ai, 'trae', 'ai should parse');
|
|
110
|
+
assert.strictEqual(combo.target, '/proj', 'target should parse');
|
|
111
|
+
assert.strictEqual(combo.force, true, 'force should parse');
|
|
112
|
+
assert.strictEqual(combo.global, false, 'target forces project mode');
|
|
113
|
+
|
|
114
|
+
console.log('mode.test.js: all parseArgs tests passed');
|
|
100
115
|
}
|
|
101
116
|
|
|
102
117
|
run().catch((err) => {
|