mdpush 1.2.0 → 1.3.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdpush",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=20.0.0"
@@ -86,9 +86,37 @@ export async function skillPushCommand(dir, options) {
86
86
  if (failed) process.exit(1)
87
87
  }
88
88
 
89
- /** Install a published skill into ~/.claude/skills/<slug> (or --dest). */
90
- export async function skillInstallCommand(slug, options) {
91
- const manifestRes = await apiRequest(`/api/skills/${slug}/manifest`)
89
+ /**
90
+ * Install published skills into ~/.claude/skills/<slug> (or --dest).
91
+ * Accepts several slugs (space or comma separated); each installs
92
+ * independently — one failure doesn't abort the rest (exit 1 at the end).
93
+ */
94
+ export async function skillInstallCommand(slugs, options) {
95
+ const list = [...new Set(slugs.flatMap(s => s.split(',')).map(s => s.trim()).filter(Boolean))]
96
+ if (list.length > 1 && options.dest) {
97
+ console.log(chalk.red('--dest is ambiguous with multiple skills — install them one at a time.'))
98
+ process.exit(2)
99
+ }
100
+
101
+ const failedSlugs = []
102
+ for (const slug of list) {
103
+ try {
104
+ await installOneSkill(slug, options)
105
+ } catch (err) {
106
+ console.log(chalk.red(`✖ ${slug}: ${err.message}`))
107
+ failedSlugs.push(slug)
108
+ }
109
+ }
110
+ if (list.length > 1) {
111
+ console.log(`\n${chalk.green(`${list.length - failedSlugs.length} skill(s) installed`)}${failedSlugs.length ? `, ${chalk.red(`${failedSlugs.length} failed (${failedSlugs.join(', ')})`)}` : ''}`)
112
+ }
113
+ if (failedSlugs.length) process.exit(1)
114
+ }
115
+
116
+ /** Install one skill. `?source=cli-install` marks a real install so the
117
+ * server bumps install_count (detail-page manifest fetches don't). */
118
+ async function installOneSkill(slug, options) {
119
+ const manifestRes = await apiRequest(`/api/skills/${slug}/manifest?source=cli-install`)
92
120
  const manifest = await manifestRes.json()
93
121
 
94
122
  const dest = path.resolve(options.dest || path.join(os.homedir(), '.claude', 'skills', slug))
@@ -115,7 +143,8 @@ export async function skillInstallCommand(slug, options) {
115
143
  }
116
144
  }
117
145
  console.log(`\n${chalk.green(`${success} installed`)}${failed ? `, ${chalk.red(`${failed} failed`)}` : ''}`)
118
- if (failed) process.exit(1)
146
+ // Throw (not exit) so a batch install can continue with the next slug.
147
+ if (failed) throw new Error(`${failed} file(s) failed`)
119
148
  }
120
149
 
121
150
  /** List published skills. */
package/src/index.js CHANGED
@@ -33,9 +33,9 @@ skill.command('push')
33
33
  .action(skillPushCommand)
34
34
 
35
35
  skill.command('install')
36
- .description('Install a published skill into ~/.claude/skills/<slug>')
37
- .argument('<slug>', 'Skill slug (see: mdpush skill list)')
38
- .option('-d, --dest <path>', 'Destination directory (default: ~/.claude/skills/<slug>)')
36
+ .description('Install published skills into ~/.claude/skills/<slug>')
37
+ .argument('<slugs...>', 'Skill slug(s) — space or comma separated (see: mdpush skill list)')
38
+ .option('-d, --dest <path>', 'Destination directory (single skill only)')
39
39
  .action(skillInstallCommand)
40
40
 
41
41
  skill.command('list')