@cremini/skillpack 1.0.5 → 1.0.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/README.md CHANGED
@@ -27,14 +27,14 @@ Step-by-Step
27
27
  3. Add prompts to orchestrate and organize skills you added to accomplish tasks
28
28
  4. (Optional) bundle the result as a zip
29
29
 
30
- ### Initialize from an Existing Config
30
+ ### Initialize with Configuration
31
31
 
32
32
  ```bash
33
33
  npx @cremini/skillpack init --config ./skillpack.json
34
34
  npx @cremini/skillpack init commic_explainer --config https://raw.githubusercontent.com/CreminiAI/skillpack/refs/heads/main/examples/commic_explainer.json
35
35
  ```
36
36
 
37
- This loads a local or remote config, writes `skillpack.json` into the target directory, installs the configured skills, and skips zip packaging unless you pass `--bundle`.
37
+ Bootstrap a SkillPack using a local file or remote URL.
38
38
 
39
39
  ### Step-by-Step Commands
40
40
 
@@ -73,11 +73,11 @@ The extracted archive looks like this:
73
73
  skillpack/
74
74
  ├── skillpack.json # Pack configuration
75
75
  ├── skills/ # Collected SKILL.md files
76
- ├── server/ # Express backend
77
- ├── web/ # Web chat UI
76
+ ├── server/ # Runtime backend
77
+ ├── web/ # Runtime web UI
78
78
  ├── start.sh # One-click launcher for macOS/Linux
79
79
  ├── start.bat # One-click launcher for Windows
80
- └── README.md
80
+ └── README.md # Runtime guide
81
81
  ```
82
82
 
83
83
  ### Run the Skill Pack
package/dist/cli.js CHANGED
@@ -5,8 +5,8 @@ import { Command } from "commander";
5
5
  import chalk8 from "chalk";
6
6
 
7
7
  // src/commands/create.ts
8
- import fs4 from "fs";
9
- import path4 from "path";
8
+ import fs5 from "fs";
9
+ import path5 from "path";
10
10
  import inquirer from "inquirer";
11
11
  import chalk3 from "chalk";
12
12
 
@@ -114,11 +114,10 @@ function configExists(workDir) {
114
114
  }
115
115
 
116
116
  // src/core/bundler.ts
117
- import fs3 from "fs";
118
- import path3 from "path";
117
+ import fs4 from "fs";
118
+ import path4 from "path";
119
119
  import archiver from "archiver";
120
120
  import chalk2 from "chalk";
121
- import { fileURLToPath } from "url";
122
121
 
123
122
  // src/core/skill-manager.ts
124
123
  import { spawnSync } from "child_process";
@@ -313,25 +312,98 @@ function removeSkill(workDir, skillName) {
313
312
  return true;
314
313
  }
315
314
 
316
- // src/core/bundler.ts
315
+ // src/core/runtime-template.ts
316
+ import fs3 from "fs";
317
+ import path3 from "path";
318
+ import { fileURLToPath } from "url";
317
319
  var __dirname = path3.dirname(fileURLToPath(import.meta.url));
318
320
  function getRuntimeDir() {
319
321
  const projectRoot = path3.resolve(__dirname, "..");
320
322
  return path3.join(projectRoot, "runtime");
321
323
  }
324
+ function assertRuntimeDirExists(runtimeDir) {
325
+ if (!fs3.existsSync(runtimeDir)) {
326
+ throw new Error(`Runtime directory not found: ${runtimeDir}`);
327
+ }
328
+ }
329
+ function collectRuntimeTemplateEntries(runtimeDir) {
330
+ assertRuntimeDirExists(runtimeDir);
331
+ const entries = [];
332
+ function visit(currentDir, relativeDir = "") {
333
+ const dirEntries = fs3.readdirSync(currentDir, { withFileTypes: true });
334
+ for (const dirEntry of dirEntries) {
335
+ if (dirEntry.name === "node_modules") {
336
+ continue;
337
+ }
338
+ const absolutePath = path3.join(currentDir, dirEntry.name);
339
+ const relativePath = relativeDir ? path3.posix.join(relativeDir, dirEntry.name) : dirEntry.name;
340
+ const stats = fs3.statSync(absolutePath);
341
+ if (dirEntry.isDirectory()) {
342
+ entries.push({
343
+ absolutePath,
344
+ relativePath,
345
+ stats,
346
+ type: "directory"
347
+ });
348
+ visit(absolutePath, relativePath);
349
+ continue;
350
+ }
351
+ if (dirEntry.isFile()) {
352
+ entries.push({
353
+ absolutePath,
354
+ relativePath,
355
+ stats,
356
+ type: "file"
357
+ });
358
+ }
359
+ }
360
+ }
361
+ visit(runtimeDir);
362
+ return entries;
363
+ }
364
+ function copyRuntimeTemplate(runtimeDir, workDir) {
365
+ const entries = collectRuntimeTemplateEntries(runtimeDir);
366
+ for (const entry of entries) {
367
+ const destinationPath = path3.join(workDir, entry.relativePath);
368
+ if (entry.type === "directory") {
369
+ fs3.mkdirSync(destinationPath, { recursive: true });
370
+ continue;
371
+ }
372
+ fs3.mkdirSync(path3.dirname(destinationPath), { recursive: true });
373
+ fs3.copyFileSync(entry.absolutePath, destinationPath);
374
+ fs3.chmodSync(destinationPath, entry.stats.mode);
375
+ }
376
+ }
377
+ function addRuntimeFiles(archive, runtimeDir, prefix) {
378
+ const entries = collectRuntimeTemplateEntries(runtimeDir);
379
+ for (const entry of entries) {
380
+ const archivePath = `${prefix}/${entry.relativePath}`;
381
+ if (entry.type === "directory") {
382
+ archive.append("", {
383
+ name: `${archivePath}/`,
384
+ mode: entry.stats.mode
385
+ });
386
+ continue;
387
+ }
388
+ archive.file(entry.absolutePath, {
389
+ name: archivePath,
390
+ mode: entry.stats.mode
391
+ });
392
+ }
393
+ }
394
+
395
+ // src/core/bundler.ts
322
396
  async function bundle(workDir) {
323
397
  const config = loadConfig(workDir);
324
398
  const zipName = `${config.name}.zip`;
325
- const zipPath = path3.join(workDir, zipName);
399
+ const zipPath = path4.join(workDir, zipName);
326
400
  const runtimeDir = getRuntimeDir();
327
- if (!fs3.existsSync(runtimeDir)) {
328
- throw new Error(`Runtime directory not found: ${runtimeDir}`);
329
- }
401
+ assertRuntimeDirExists(runtimeDir);
330
402
  installConfiguredSkills(workDir, config);
331
403
  syncSkillDescriptions(workDir, config);
332
404
  saveConfig(workDir, config);
333
405
  console.log(chalk2.blue(`Packaging ${config.name}...`));
334
- const output = fs3.createWriteStream(zipPath);
406
+ const output = fs4.createWriteStream(zipPath);
335
407
  const archive = archiver("zip", { zlib: { level: 9 } });
336
408
  return new Promise((resolve, reject) => {
337
409
  output.on("close", () => {
@@ -348,55 +420,23 @@ async function bundle(workDir) {
348
420
  archive.file(getPackPath(workDir), {
349
421
  name: `${prefix}/${PACK_FILE}`
350
422
  });
351
- const skillsDir = path3.join(workDir, "skills");
352
- if (fs3.existsSync(skillsDir)) {
423
+ const skillsDir = path4.join(workDir, "skills");
424
+ if (fs4.existsSync(skillsDir)) {
353
425
  archive.directory(skillsDir, `${prefix}/skills`);
354
426
  }
355
427
  addRuntimeFiles(archive, runtimeDir, prefix);
356
428
  archive.finalize();
357
429
  });
358
430
  }
359
- function addRuntimeFiles(archive, runtimeDir, prefix) {
360
- const serverDir = path3.join(runtimeDir, "server");
361
- if (fs3.existsSync(serverDir)) {
362
- archive.glob(
363
- "**/*",
364
- {
365
- cwd: serverDir,
366
- ignore: ["node_modules/**"]
367
- },
368
- { prefix: `${prefix}/server` }
369
- );
370
- }
371
- const webDir = path3.join(runtimeDir, "web");
372
- if (fs3.existsSync(webDir)) {
373
- archive.directory(webDir, `${prefix}/web`);
374
- }
375
- const scriptsDir = path3.join(runtimeDir, "scripts");
376
- if (fs3.existsSync(scriptsDir)) {
377
- const startSh = path3.join(scriptsDir, "start.sh");
378
- if (fs3.existsSync(startSh)) {
379
- archive.file(startSh, { name: `${prefix}/start.sh`, mode: 493 });
380
- }
381
- const startBat = path3.join(scriptsDir, "start.bat");
382
- if (fs3.existsSync(startBat)) {
383
- archive.file(startBat, { name: `${prefix}/start.bat` });
384
- }
385
- }
386
- const readme = path3.join(runtimeDir, "README.md");
387
- if (fs3.existsSync(readme)) {
388
- archive.file(readme, { name: `${prefix}/README.md` });
389
- }
390
- }
391
431
 
392
432
  // src/commands/create.ts
393
433
  function parseSkillNames(value) {
394
434
  return value.split(",").map((name) => name.trim()).filter(Boolean);
395
435
  }
396
436
  async function createCommand(directory) {
397
- const workDir = directory ? path4.resolve(directory) : process.cwd();
437
+ const workDir = directory ? path5.resolve(directory) : process.cwd();
398
438
  if (directory) {
399
- fs4.mkdirSync(workDir, { recursive: true });
439
+ fs5.mkdirSync(workDir, { recursive: true });
400
440
  }
401
441
  if (configExists(workDir)) {
402
442
  const { overwrite } = await inquirer.prompt([
@@ -515,8 +555,8 @@ async function createCommand(directory) {
515
555
  }
516
556
 
517
557
  // src/commands/init.ts
518
- import fs5 from "fs";
519
- import path5 from "path";
558
+ import fs6 from "fs";
559
+ import path6 from "path";
520
560
  import inquirer2 from "inquirer";
521
561
  import chalk4 from "chalk";
522
562
  function isHttpUrl(value) {
@@ -536,17 +576,17 @@ async function readConfigSource(source) {
536
576
  }
537
577
  raw = await response.text();
538
578
  } else {
539
- const filePath = path5.resolve(source);
540
- raw = fs5.readFileSync(filePath, "utf-8");
579
+ const filePath = path6.resolve(source);
580
+ raw = fs6.readFileSync(filePath, "utf-8");
541
581
  }
542
582
  const parsed = JSON.parse(raw);
543
583
  validateConfigShape(parsed, source);
544
584
  return parsed;
545
585
  }
546
586
  async function initCommand(directory, options) {
547
- const workDir = directory ? path5.resolve(directory) : process.cwd();
587
+ const workDir = directory ? path6.resolve(directory) : process.cwd();
548
588
  if (directory) {
549
- fs5.mkdirSync(workDir, { recursive: true });
589
+ fs6.mkdirSync(workDir, { recursive: true });
550
590
  }
551
591
  if (configExists(workDir)) {
552
592
  const { overwrite } = await inquirer2.prompt([
@@ -569,12 +609,14 @@ async function initCommand(directory, options) {
569
609
  `));
570
610
  installConfiguredSkills(workDir, config);
571
611
  refreshDescriptionsAndSave(workDir, config);
612
+ copyRuntimeTemplate(getRuntimeDir(), workDir);
572
613
  if (options.bundle) {
573
614
  await bundle(workDir);
574
615
  }
575
616
  console.log(chalk4.green(`
576
617
  ${PACK_FILE} saved
577
618
  `));
619
+ console.log(chalk4.green(" Runtime template expanded.\n"));
578
620
  console.log(chalk4.green(" Initialization complete.\n"));
579
621
  if (!options.bundle) {
580
622
  console.log(
@@ -706,16 +748,18 @@ function registerPromptsCommand(program2) {
706
748
  }
707
749
 
708
750
  // src/cli.ts
709
- import fs6 from "fs";
751
+ import fs7 from "fs";
710
752
  var packageJson = JSON.parse(
711
- fs6.readFileSync(new URL("../package.json", import.meta.url), "utf-8")
753
+ fs7.readFileSync(new URL("../package.json", import.meta.url), "utf-8")
712
754
  );
713
755
  var program = new Command();
714
756
  program.name("skillpack").description("Assemble, package, and run Agent Skills packs").version(packageJson.version);
715
757
  program.command("create [directory]").description("Create a skills pack interactively").action(async (directory) => {
716
758
  await createCommand(directory);
717
759
  });
718
- program.command("init [directory]").description("Initialize a skills pack from a local config file or URL").requiredOption("--config <path-or-url>", "Path or URL to a skillpack.json file").option("--bundle", "Bundle as a zip after initialization").action(
760
+ program.command("init [directory]").description(
761
+ "Initialize a skills pack from a local config file or URL and expand runtime files"
762
+ ).requiredOption("--config <path-or-url>", "Path or URL to a skillpack.json file").option("--bundle", "Bundle as a zip after initialization").action(
719
763
  async (directory, options) => {
720
764
  await initCommand(directory, options);
721
765
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cremini/skillpack",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Turn Skills into a Standalone App with UI",
5
5
  "type": "module",
6
6
  "repository": {
@@ -16,14 +16,7 @@
16
16
  },
17
17
  "files": [
18
18
  "dist",
19
- "runtime/README.md",
20
- "runtime/scripts",
21
- "runtime/server/chat-proxy.js",
22
- "runtime/server/index.js",
23
- "runtime/server/package.json",
24
- "runtime/server/routes.js",
25
- "runtime/server/skills-loader.js",
26
- "runtime/web",
19
+ "runtime",
27
20
  "README.md",
28
21
  "LICENSE"
29
22
  ],
@@ -61,4 +54,4 @@
61
54
  "tsup": "^8.5.1",
62
55
  "typescript": "^5.9.3"
63
56
  }
64
- }
57
+ }