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 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 always puts the `iterate` CLI on your PATH so a single
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, use a manual install instead — copy `SKILL.md` + `config/` +
48
- > `scripts/` + `templates/` to your assistant dir, or run
49
- > `python scripts/install.py install` directly. If the CLI install fails, you can
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
- > **注意:** 安装器总是会把你 PATH 上的 `iterate` CLI 装好,所以一条命令就能同时
46
- > 得到技能和 CLI。如果**不**想自动安装 CLI,请改用手动安装——把
47
- > `SKILL.md` + `config/` + `scripts/` + `templates/` 复制到你的助手目录,或直接运行
48
- > `python scripts/install.py install`。如果 CLI 安装失败,你之后仍可从检出目录用
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 { global: globalInstall = true, ai = null, token = null, target = null, force = false } = options;
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
- // Install the iterate CLI so `iterate onboard` works right after install.
499
- await installCli(pythonBin, sourceDir);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iterate-skill-installer",
3
- "version": "2.4.1",
3
+ "version": "2.4.3",
4
4
  "description": "One-command installer for iterate-skill across AI coding assistants",
5
5
  "main": "lib/installer.js",
6
6
  "bin": {
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) => {