create-harper 1.4.6 → 1.4.7

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/lib/init.js CHANGED
@@ -7,6 +7,7 @@ import { getEnvVars } from './steps/getEnvVars.js';
7
7
  import { getPackageName } from './steps/getPackageName.js';
8
8
  import { getProjectName } from './steps/getProjectName.js';
9
9
  import { getRunAppImmediately } from './steps/getRunAppImmediately.js';
10
+ import { getSkills } from './steps/getSkills.js';
10
11
  import { getTemplate } from './steps/getTemplate.js';
11
12
  import { handleExistingDir } from './steps/handleExistingDir.js';
12
13
  import { helpAgents } from './steps/helpAgents.js';
@@ -67,13 +68,18 @@ export async function init() {
67
68
  if (immediateResult.cancelled) { return cancel(); }
68
69
  const { immediate } = immediateResult;
69
70
 
71
+ // Choose skills to install
72
+ const skillsResult = await getSkills(interactive, args.skills, args.agents, args.skipSkills);
73
+ if (skillsResult.cancelled) { return cancel(); }
74
+ const { selectedSkills, selectedAgents } = skillsResult;
75
+
70
76
  // Write out the contents based on all prior steps.
71
77
  const cwd = process.cwd();
72
78
  const root = path.join(cwd, targetDir);
73
79
  scaffoldProject(root, projectName, packageName, template, envVars);
74
80
 
75
81
  // Log out the next steps.
76
- installAndOptionallyStart(root, pkgManager, immediate, args.skipInstall);
82
+ installAndOptionallyStart(root, pkgManager, immediate, args.skipInstall, selectedSkills, selectedAgents);
77
83
  } catch (e) {
78
84
  console.error(e);
79
85
  }
package/lib/install.js CHANGED
@@ -7,22 +7,43 @@ import { run } from './run.js';
7
7
  *
8
8
  * @param {string} root - The root directory of the project.
9
9
  * @param {string} agent - The package manager agent (e.g., 'npm', 'pnpm', 'yarn', 'bun').
10
+ * @param {string[]} [selectedSkills] - The skills to install.
11
+ * @param {string[]} [selectedAgents] - The agents to install skills to.
10
12
  */
11
- export function install(root, agent) {
13
+ export function install(root, agent, selectedSkills = [], selectedAgents = []) {
12
14
  if (process.env._HARPER_TEST_CLI) {
13
15
  prompts.log.step(
14
16
  `Installing dependencies with ${agent}... (skipped in test)`,
15
17
  );
16
18
  return;
17
19
  }
20
+
21
+ if (selectedSkills.length > 0) {
22
+ prompts.log.step('Installing Harper skills...');
23
+
24
+ const command = ['npx', '-y', 'skills', 'add', 'harperfast/skills'];
25
+
26
+ if (selectedSkills.includes('*') && selectedAgents.includes('*')) {
27
+ command.push('--all');
28
+ } else {
29
+ if (selectedSkills.length > 0) {
30
+ command.push('--skill', ...selectedSkills);
31
+ }
32
+ if (selectedAgents.length > 0) {
33
+ command.push('--agent', ...selectedAgents);
34
+ }
35
+ command.push('--yes');
36
+ }
37
+
38
+ run(command, {
39
+ stdio: 'inherit',
40
+ cwd: root,
41
+ });
42
+ }
43
+
18
44
  prompts.log.step(`Installing dependencies with ${agent}...`);
19
45
  run(getInstallCommand(agent), {
20
46
  stdio: 'inherit',
21
47
  cwd: root,
22
48
  });
23
- prompts.log.step('Installing Harper skills...');
24
- run(['npx', '-y', 'skills', 'add', 'harperfast/skills', '--all', '--yes'], {
25
- stdio: 'inherit',
26
- cwd: root,
27
- });
28
49
  }
@@ -0,0 +1,61 @@
1
+ import * as prompts from '@clack/prompts';
2
+
3
+ /**
4
+ * Step 6: Choose whether to install Harper AI skills and for which agents.
5
+ *
6
+ * @param {boolean} interactive - Whether the CLI is running in interactive mode.
7
+ * @param {string} [argSkills] - The skills specified in the command line args.
8
+ * @param {string} [argAgents] - The agents specified in the command line args.
9
+ * @param {boolean} [argSkipSkills] - Whether to skip skills installation.
10
+ * @returns {Promise<{selectedSkills: string[], selectedAgents: string[], cancelled: boolean}>}
11
+ */
12
+ export async function getSkills(interactive, argSkills, argAgents, argSkipSkills) {
13
+ if (argSkipSkills) {
14
+ return { selectedSkills: [], selectedAgents: [], cancelled: false };
15
+ }
16
+
17
+ let selectedSkills = argSkills ? argSkills.split(',') : ['*'];
18
+ let selectedAgents = argAgents ? argAgents.split(',') : [];
19
+
20
+ if (interactive && !argSkills && !argAgents) {
21
+ const installSkills = await prompts.confirm({
22
+ message: 'Would you like to install Harper AI skills to your IDE/agent?',
23
+ initialValue: true,
24
+ });
25
+
26
+ if (prompts.isCancel(installSkills)) {
27
+ return { selectedSkills: [], selectedAgents: [], cancelled: true };
28
+ }
29
+
30
+ if (!installSkills) {
31
+ return { selectedSkills: [], selectedAgents: [], cancelled: false };
32
+ }
33
+
34
+ const agents = await prompts.multiselect({
35
+ message: 'Which AI agents do you use? (Press <space> to select, <enter> to submit)',
36
+ options: [
37
+ { value: 'auto', label: 'Just detect', hint: 'Auto-detect current environment' },
38
+ { value: 'claude-code', label: 'Claude Code', hint: 'https://claude.com/product/claude-code' },
39
+ { value: 'codex', label: 'OpenAI Codex', hint: 'https://chatgpt.com/codex' },
40
+ { value: 'copilot', label: 'GitHub Copilot', hint: 'https://github.com/features/copilot' },
41
+ { value: 'cursor', label: 'Cursor', hint: 'https://cursor.com/' },
42
+ { value: 'windsurf', label: 'Windsurf', hint: 'https://windsurf.com/' },
43
+ { value: 'all', label: 'All supported agents', hint: '40+ agents' },
44
+ ],
45
+ required: false,
46
+ });
47
+
48
+ if (prompts.isCancel(agents)) {
49
+ return { selectedSkills: [], selectedAgents: [], cancelled: true };
50
+ }
51
+
52
+ selectedAgents = agents;
53
+ if (agents.includes('all')) {
54
+ selectedAgents = ['*'];
55
+ } else if (agents.includes('auto')) {
56
+ selectedAgents = [];
57
+ }
58
+ }
59
+
60
+ return { selectedSkills, selectedAgents, cancelled: false };
61
+ }
@@ -12,10 +12,12 @@ import { start } from '../start.js';
12
12
  * @param {string} pkgManager - The detected or selected package manager.
13
13
  * @param {boolean} immediate - Whether to immediately install and start the project.
14
14
  * @param {boolean} skipInstall - Whether to skip the installation step.
15
+ * @param {string[]} selectedSkills - The skills to install.
16
+ * @param {string[]} selectedAgents - The agents to install skills to.
15
17
  */
16
- export function installAndOptionallyStart(root, pkgManager, immediate, skipInstall) {
18
+ export function installAndOptionallyStart(root, pkgManager, immediate, skipInstall, selectedSkills, selectedAgents) {
17
19
  if (!skipInstall) {
18
- install(root, pkgManager);
20
+ install(root, pkgManager, selectedSkills, selectedAgents);
19
21
  }
20
22
 
21
23
  if (immediate && !skipInstall) {
@@ -9,14 +9,18 @@ export function parseArgv(rawArgv) {
9
9
  'interactive',
10
10
  'overwrite',
11
11
  'skipInstall',
12
+ 'skipSkills',
12
13
  'version',
13
14
  ],
14
15
  string: [
16
+ 'agents',
15
17
  'deploymentURL',
16
18
  'deploymentUsername',
19
+ 'skills',
17
20
  'template',
18
21
  ],
19
22
  alias: {
23
+ a: 'agents',
20
24
  c: 'deploymentURL',
21
25
  'deployment-url': 'deploymentURL',
22
26
  'deployment-username': 'deploymentUsername',
@@ -25,6 +29,7 @@ export function parseArgv(rawArgv) {
25
29
  o: 'overwrite',
26
30
  s: 'skipInstall',
27
31
  'skip-install': 'skipInstall',
32
+ 'skip-skills': 'skipSkills',
28
33
  t: 'template',
29
34
  u: 'deploymentUsername',
30
35
  v: 'version',
@@ -49,6 +54,7 @@ export function parseArgv(rawArgv) {
49
54
  }
50
55
 
51
56
  return {
57
+ agents: argv.agents,
52
58
  deploymentURL: argv.deploymentURL,
53
59
  deploymentUsername: argv.deploymentUsername,
54
60
  help: argv.help,
@@ -56,6 +62,8 @@ export function parseArgv(rawArgv) {
56
62
  interactive: argv.interactive ?? process.stdin.isTTY,
57
63
  overwrite: argv.overwrite,
58
64
  skipInstall: argv.skipInstall,
65
+ skipSkills: argv.skipSkills,
66
+ skills: argv.skills,
59
67
  targetDir: positionalArgs[0] ? formatTargetDir(String(positionalArgs[0])) : undefined,
60
68
  template: argv.template,
61
69
  version: argv.version,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-harper",
3
3
  "description": "Scaffold a new Harper project in JavaScript or TypeScript.",
4
- "version": "1.4.6",
4
+ "version": "1.4.7",
5
5
  "type": "module",
6
6
  "author": {
7
7
  "name": "HarperDB",