pikakit 3.9.102 → 3.9.104

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
@@ -4,7 +4,7 @@
4
4
 
5
5
  ### Transform your AI Agent into a FAANG-level engineering team
6
6
 
7
- [![npm version](https://img.shields.io/badge/npm-v3.9.102-7c3aed?style=for-the-badge&logo=npm&logoColor=white&labelColor=18181b)](https://www.npmjs.com/package/pikakit)
7
+ [![npm version](https://img.shields.io/badge/npm-v3.9.104-7c3aed?style=for-the-badge&logo=npm&logoColor=white&labelColor=18181b)](https://www.npmjs.com/package/pikakit)
8
8
  [![Skills](https://img.shields.io/badge/skills-51-06b6d4?style=for-the-badge&labelColor=18181b)](https://github.com/pikakit/agent-skills)
9
9
  [![Agents](https://img.shields.io/badge/agents-21-f59e0b?style=for-the-badge&labelColor=18181b)](https://github.com/pikakit/agent-skills)
10
10
  [![Workflows](https://img.shields.io/badge/workflows-18-10b981?style=for-the-badge&labelColor=18181b)](https://github.com/pikakit/agent-skills)
@@ -396,7 +396,7 @@ UNLICENSED — See [LICENSE](LICENSE) for details.
396
396
 
397
397
  <div align="center">
398
398
 
399
- **⚡ PikaKit v3.9.102**
399
+ **⚡ PikaKit v3.9.104**
400
400
 
401
401
  *Composable Skills · Coordinated Agents · Intelligent Execution*
402
402
 
@@ -26,6 +26,19 @@ const pkg = require('../../../package.json');
26
26
  * @param {string} spec - Skill spec (org/repo or org/repo#skill)
27
27
  */
28
28
  export async function run(spec) {
29
+ // Global timeout safety net (5 minutes)
30
+ const GLOBAL_TIMEOUT_MS = 5 * 60 * 1000;
31
+ const globalTimer = setTimeout(() => {
32
+ console.error(c.red("\n⏱ Installation timed out after 5 minutes."));
33
+ console.error(c.dim("This usually means a network issue or a hung process."));
34
+ console.error(c.dim("Try again with: npx pikakit --force"));
35
+ process.exit(1);
36
+ }, GLOBAL_TIMEOUT_MS);
37
+ globalTimer.unref(); // Don't keep process alive just for this timer
38
+
39
+ // Non-interactive mode: auto-accept defaults when stdin is not a TTY
40
+ const isInteractive = process.stdin.isTTY !== false;
41
+
29
42
  if (!spec) {
30
43
  fatal("Missing skill spec. Usage: add-skill <org/repo>");
31
44
  return;
@@ -49,7 +62,6 @@ export async function run(spec) {
49
62
 
50
63
  const url = `https://github.com/${org}/${repo}.git`;
51
64
 
52
- stepLine();
53
65
  step("Source: " + c.cyan(url));
54
66
 
55
67
  const s = spinner();
@@ -63,8 +75,15 @@ export async function run(spec) {
63
75
 
64
76
  for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
65
77
  try {
66
- await execAsync(`git clone --depth=1 ${url} "${tmp}"`, { timeout: 60000 });
67
- if (ref) await execAsync(`git -C "${tmp}" checkout ${ref}`, { timeout: 30000 });
78
+ await execAsync(`git clone --depth=1 ${url} "${tmp}"`, {
79
+ timeout: 60000,
80
+ maxBuffer: 10 * 1024 * 1024,
81
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
82
+ });
83
+ if (ref) await execAsync(`git -C "${tmp}" checkout ${ref}`, {
84
+ timeout: 30000,
85
+ maxBuffer: 10 * 1024 * 1024
86
+ });
68
87
  lastError = null;
69
88
  break;
70
89
  } catch (err) {
@@ -258,21 +277,28 @@ export async function run(spec) {
258
277
  return a.localeCompare(b);
259
278
  });
260
279
 
261
- // Show categories in multiselect
262
- const selectedCategories = await multiselect({
263
- message: `Found ${skillsInRepo.length} skills — ${c.gray("[")}${c.cyan("Space")}${c.gray("]")}select ${c.gray("[")}${c.cyan("Enter")}${c.gray("]")}continue`,
264
- options: sortedCategories.map(cat => ({
265
- label: `${cat} (${grouped[cat].length} skills)`,
266
- value: cat
267
- })),
268
- initialValues: sortedCategories, // Pre-select all
269
- required: true
270
- });
280
+ // Non-interactive: auto-select all categories
281
+ let selectedCategories;
282
+ if (!isInteractive || FORCE) {
283
+ selectedCategories = sortedCategories;
284
+ step(c.dim(`Auto-selected all ${sortedCategories.length} categories (non-interactive mode)`));
285
+ } else {
286
+ // Show categories in multiselect
287
+ selectedCategories = await multiselect({
288
+ message: `Found ${skillsInRepo.length} skills — ${c.gray("[")}${c.cyan("Space")}${c.gray("]")}select ${c.gray("[")}${c.cyan("Enter")}${c.gray("]")}continue`,
289
+ options: sortedCategories.map(cat => ({
290
+ label: `${cat} (${grouped[cat].length} skills)`,
291
+ value: cat
292
+ })),
293
+ initialValues: sortedCategories, // Pre-select all
294
+ required: true
295
+ });
271
296
 
272
- if (isCancel(selectedCategories)) {
273
- cancel("Cancelled.");
274
- fs.rmSync(tmp, { recursive: true, force: true });
275
- return;
297
+ if (isCancel(selectedCategories)) {
298
+ cancel("Cancelled.");
299
+ fs.rmSync(tmp, { recursive: true, force: true });
300
+ return;
301
+ }
276
302
  }
277
303
 
278
304
  // Clear multiselect default summary line (inline categories wrap)
@@ -330,9 +356,10 @@ export async function run(spec) {
330
356
  { name: "Antigravity", cli: "antigravity" }
331
357
  ];
332
358
 
333
- for (const ide of vsCodeBasedIDEs) {
359
+ // Detect IDEs in parallel (not sequentially) to avoid cumulative timeout
360
+ await Promise.allSettled(vsCodeBasedIDEs.map(async (ide) => {
334
361
  try {
335
- await execAsync(`${ide.cli} --version`, { timeout: 5000 });
362
+ await execAsync(`${ide.cli} --version`, { timeout: 3000 });
336
363
  detectedIDEs.push(ide);
337
364
  } catch {
338
365
  // Fallback: check known installation paths
@@ -344,16 +371,20 @@ export async function run(spec) {
344
371
  detectedIDEs.push(ide);
345
372
  }
346
373
  }
347
- }
374
+ }));
348
375
 
349
376
  if (detectedIDEs.length > 0) {
350
- const installExt = await confirm({
351
- message: `Install PikaKit Engine extension? ${c.dim(`(${detectedIDEs.map(i => i.name).join(", ")})`)}`,
352
- initialValue: true
353
- });
354
-
355
- if (!isCancel(installExt) && installExt) {
377
+ if (!isInteractive || FORCE) {
356
378
  wantExtension = true;
379
+ } else {
380
+ const installExt = await confirm({
381
+ message: `Install PikaKit Engine extension? ${c.dim(`(${detectedIDEs.map(i => i.name).join(", ")})`)}`,
382
+ initialValue: true
383
+ });
384
+
385
+ if (!isCancel(installExt) && installExt) {
386
+ wantExtension = true;
387
+ }
357
388
  }
358
389
  }
359
390
  }
@@ -377,7 +408,13 @@ export async function run(spec) {
377
408
  // --- Select agents (Vercel-style) ---
378
409
  const { selectAgentsPrompt, selectScopePrompt, selectMethodPrompt } = await import("../ui.js");
379
410
 
380
- const selectedAgents = await selectAgentsPrompt(detectedAgents);
411
+ let selectedAgents;
412
+ if (!isInteractive || FORCE) {
413
+ selectedAgents = detectedAgents;
414
+ step(c.dim(`Auto-selected ${detectedAgents.length} agents (non-interactive mode)`));
415
+ } else {
416
+ selectedAgents = await selectAgentsPrompt(detectedAgents);
417
+ }
381
418
 
382
419
  if (!selectedAgents || selectedAgents.length === 0) {
383
420
  fs.rmSync(tmp, { recursive: true, force: true });
@@ -388,27 +425,36 @@ export async function run(spec) {
388
425
  let isGlobal = GLOBAL;
389
426
 
390
427
  if (!GLOBAL) {
391
- const scope = await selectScopePrompt();
428
+ if (!isInteractive || FORCE) {
429
+ isGlobal = false; // Default to project scope
430
+ } else {
431
+ const scope = await selectScopePrompt();
392
432
 
393
- if (!scope) {
394
- fs.rmSync(tmp, { recursive: true, force: true });
395
- return;
396
- }
433
+ if (!scope) {
434
+ fs.rmSync(tmp, { recursive: true, force: true });
435
+ return;
436
+ }
397
437
 
398
- isGlobal = scope === "global";
438
+ isGlobal = scope === "global";
439
+ }
399
440
  }
400
441
 
401
442
  // --- Select installation method ---
402
- const installMethod = await selectMethodPrompt();
443
+ let installMethod;
444
+ if (!isInteractive || FORCE) {
445
+ installMethod = "symlink"; // Default to symlink
446
+ } else {
447
+ installMethod = await selectMethodPrompt();
403
448
 
404
- if (!installMethod) {
405
- fs.rmSync(tmp, { recursive: true, force: true });
406
- return;
449
+ if (!installMethod) {
450
+ fs.rmSync(tmp, { recursive: true, force: true });
451
+ return;
452
+ }
407
453
  }
408
454
 
409
- // Confirmation (skip if --force)
410
- let shouldProceed = FORCE;
411
- if (!FORCE) {
455
+ // Confirmation (skip if --force or non-interactive)
456
+ let shouldProceed = FORCE || !isInteractive;
457
+ if (!shouldProceed) {
412
458
  shouldProceed = await confirm({ message: "Proceed with installation?", initialValue: true });
413
459
 
414
460
  if (isCancel(shouldProceed) || !shouldProceed) {
@@ -458,118 +504,120 @@ export async function run(spec) {
458
504
  // If skillsDir is .../skills, then baseAgentDir is parent (.agent)
459
505
  const baseAgentDir = skillsDir ? path.dirname(skillsDir) : path.join(tmp, ".agent");
460
506
 
461
- // Install workflows (silent)
462
- const workflowsDir = path.join(baseAgentDir, "workflows");
463
- const targetWorkflowsDir = path.join(WORKSPACE, "..", "workflows");
507
+ // --- Post-install file copy phase (wrapped in try/catch for robustness) ---
464
508
  let workflowsInstalled = 0;
465
-
466
- if (fs.existsSync(workflowsDir)) {
467
- fs.mkdirSync(targetWorkflowsDir, { recursive: true });
468
- const workflows = fs.readdirSync(workflowsDir).filter(f => f.endsWith(".md"));
469
- for (const wf of workflows) {
470
- const src = path.join(workflowsDir, wf);
471
- const dest = path.join(targetWorkflowsDir, wf);
472
- if (!fs.existsSync(dest)) {
473
- fs.copyFileSync(src, dest);
474
- workflowsInstalled++;
475
- }
476
- }
477
- }
478
-
479
- // Install GEMINI.md (silent)
480
- const geminiSrc = path.join(baseAgentDir, "GEMINI.md");
481
- const geminiDest = path.join(WORKSPACE, "..", "GEMINI.md");
482
509
  let geminiInstalled = false;
483
- if (fs.existsSync(geminiSrc) && !fs.existsSync(geminiDest)) {
484
- fs.copyFileSync(geminiSrc, geminiDest);
485
- geminiInstalled = true;
486
- }
510
+ let agentsInstalled = 0;
511
+ let archInstalled = false;
512
+ let configInstalled = false;
513
+ let metricsInstalled = false;
514
+ let policyDocsInstalled = 0;
515
+ let rulesInstalled = 0;
516
+ let sharedInstalled = false;
487
517
 
488
- // Install agents (silent)
489
- const agentsDir = path.join(baseAgentDir, "agents");
518
+ const targetWorkflowsDir = path.join(WORKSPACE, "..", "workflows");
519
+ const geminiDest = path.join(WORKSPACE, "..", "GEMINI.md");
490
520
  const targetAgentsDir = path.join(WORKSPACE, "..", "agents");
491
- let agentsInstalled = 0;
521
+ const archDest = path.join(WORKSPACE, "..", "ARCHITECTURE.md");
492
522
 
493
- if (fs.existsSync(agentsDir)) {
494
- fs.mkdirSync(targetAgentsDir, { recursive: true });
495
- const agents = fs.readdirSync(agentsDir).filter(f => f.endsWith(".md"));
496
- for (const agent of agents) {
497
- const src = path.join(agentsDir, agent);
498
- const dest = path.join(targetAgentsDir, agent);
499
- if (!fs.existsSync(dest)) {
500
- fs.copyFileSync(src, dest);
501
- agentsInstalled++;
523
+ try {
524
+ // Install workflows (silent)
525
+ const workflowsDir = path.join(baseAgentDir, "workflows");
526
+ if (fs.existsSync(workflowsDir)) {
527
+ fs.mkdirSync(targetWorkflowsDir, { recursive: true });
528
+ const workflows = fs.readdirSync(workflowsDir).filter(f => f.endsWith(".md"));
529
+ for (const wf of workflows) {
530
+ const src = path.join(workflowsDir, wf);
531
+ const dest = path.join(targetWorkflowsDir, wf);
532
+ if (!fs.existsSync(dest)) {
533
+ fs.copyFileSync(src, dest);
534
+ workflowsInstalled++;
535
+ }
502
536
  }
503
537
  }
504
- }
505
-
506
- // Install ARCHITECTURE.md (silent)
507
- const archSrc = path.join(baseAgentDir, "ARCHITECTURE.md");
508
- const archDest = path.join(WORKSPACE, "..", "ARCHITECTURE.md");
509
- let archInstalled = false;
510
- if (fs.existsSync(archSrc) && !fs.existsSync(archDest)) {
511
- fs.copyFileSync(archSrc, archDest);
512
- archInstalled = true;
513
- }
514
-
515
538
 
539
+ // Install GEMINI.md (silent)
540
+ const geminiSrc = path.join(baseAgentDir, "GEMINI.md");
541
+ if (fs.existsSync(geminiSrc) && !fs.existsSync(geminiDest)) {
542
+ fs.copyFileSync(geminiSrc, geminiDest);
543
+ geminiInstalled = true;
544
+ }
516
545
 
517
- // Install config (silent)
518
- const configDir = path.join(baseAgentDir, "config");
519
- const targetConfigDir = path.join(WORKSPACE, "..", "config");
520
- let configInstalled = false;
521
- if (fs.existsSync(configDir) && !fs.existsSync(targetConfigDir)) {
522
- fs.cpSync(configDir, targetConfigDir, { recursive: true });
523
- configInstalled = true;
524
- }
546
+ // Install agents (silent)
547
+ const agentsDir = path.join(baseAgentDir, "agents");
548
+ if (fs.existsSync(agentsDir)) {
549
+ fs.mkdirSync(targetAgentsDir, { recursive: true });
550
+ const agents = fs.readdirSync(agentsDir).filter(f => f.endsWith(".md"));
551
+ for (const agent of agents) {
552
+ const src = path.join(agentsDir, agent);
553
+ const dest = path.join(targetAgentsDir, agent);
554
+ if (!fs.existsSync(dest)) {
555
+ fs.copyFileSync(src, dest);
556
+ agentsInstalled++;
557
+ }
558
+ }
559
+ }
525
560
 
561
+ // Install ARCHITECTURE.md (silent)
562
+ const archSrc = path.join(baseAgentDir, "ARCHITECTURE.md");
563
+ if (fs.existsSync(archSrc) && !fs.existsSync(archDest)) {
564
+ fs.copyFileSync(archSrc, archDest);
565
+ archInstalled = true;
566
+ }
526
567
 
568
+ // Install config (silent)
569
+ const configDir = path.join(baseAgentDir, "config");
570
+ const targetConfigDir = path.join(WORKSPACE, "..", "config");
571
+ if (fs.existsSync(configDir) && !fs.existsSync(targetConfigDir)) {
572
+ fs.cpSync(configDir, targetConfigDir, { recursive: true });
573
+ configInstalled = true;
574
+ }
527
575
 
528
- // Install metrics (silent)
529
- const metricsDir = path.join(baseAgentDir, "metrics");
530
- const targetMetricsDir = path.join(WORKSPACE, "..", "metrics");
531
- let metricsInstalled = false;
532
- if (fs.existsSync(metricsDir) && !fs.existsSync(targetMetricsDir)) {
533
- fs.cpSync(metricsDir, targetMetricsDir, { recursive: true });
534
- metricsInstalled = true;
535
- }
576
+ // Install metrics (silent)
577
+ const metricsDir = path.join(baseAgentDir, "metrics");
578
+ const targetMetricsDir = path.join(WORKSPACE, "..", "metrics");
579
+ if (fs.existsSync(metricsDir) && !fs.existsSync(targetMetricsDir)) {
580
+ fs.cpSync(metricsDir, targetMetricsDir, { recursive: true });
581
+ metricsInstalled = true;
582
+ }
536
583
 
537
- // Install policy documents (silent)
538
- const policyDocs = ["CONTINUOUS_EXECUTION_POLICY.md", "WORKFLOW_CHAINS.md"];
539
- let policyDocsInstalled = 0;
540
- for (const doc of policyDocs) {
541
- const docSrc = path.join(baseAgentDir, doc);
542
- const docDest = path.join(WORKSPACE, "..", doc);
543
- if (fs.existsSync(docSrc) && !fs.existsSync(docDest)) {
544
- fs.copyFileSync(docSrc, docDest);
545
- policyDocsInstalled++;
584
+ // Install policy documents (silent)
585
+ const policyDocs = ["CONTINUOUS_EXECUTION_POLICY.md", "WORKFLOW_CHAINS.md"];
586
+ for (const doc of policyDocs) {
587
+ const docSrc = path.join(baseAgentDir, doc);
588
+ const docDest = path.join(WORKSPACE, "..", doc);
589
+ if (fs.existsSync(docSrc) && !fs.existsSync(docDest)) {
590
+ fs.copyFileSync(docSrc, docDest);
591
+ policyDocsInstalled++;
592
+ }
546
593
  }
547
- }
548
594
 
549
- // Install rules (silent)
550
- const rulesDir = path.join(baseAgentDir, "rules");
551
- const targetRulesDir = path.join(WORKSPACE, "..", "rules");
552
- let rulesInstalled = 0;
553
- if (fs.existsSync(rulesDir)) {
554
- fs.mkdirSync(targetRulesDir, { recursive: true });
555
- const rules = fs.readdirSync(rulesDir).filter(f => f.endsWith(".md"));
556
- for (const rule of rules) {
557
- const src = path.join(rulesDir, rule);
558
- const dest = path.join(targetRulesDir, rule);
559
- if (!fs.existsSync(dest)) {
560
- fs.copyFileSync(src, dest);
561
- rulesInstalled++;
595
+ // Install rules (silent)
596
+ const rulesDir = path.join(baseAgentDir, "rules");
597
+ const targetRulesDir = path.join(WORKSPACE, "..", "rules");
598
+ if (fs.existsSync(rulesDir)) {
599
+ fs.mkdirSync(targetRulesDir, { recursive: true });
600
+ const rules = fs.readdirSync(rulesDir).filter(f => f.endsWith(".md"));
601
+ for (const rule of rules) {
602
+ const src = path.join(rulesDir, rule);
603
+ const dest = path.join(targetRulesDir, rule);
604
+ if (!fs.existsSync(dest)) {
605
+ fs.copyFileSync(src, dest);
606
+ rulesInstalled++;
607
+ }
562
608
  }
563
609
  }
564
- }
565
610
 
566
- // Install .shared (silent)
567
- const sharedDir = path.join(tmp, ".agent", ".shared");
568
- const targetSharedDir = path.join(WORKSPACE, "..", ".shared");
569
- let sharedInstalled = false;
570
- if (fs.existsSync(sharedDir) && !fs.existsSync(targetSharedDir)) {
571
- fs.cpSync(sharedDir, targetSharedDir, { recursive: true });
572
- sharedInstalled = true;
611
+ // Install .shared (silent)
612
+ const sharedDir = path.join(tmp, ".agent", ".shared");
613
+ const targetSharedDir = path.join(WORKSPACE, "..", ".shared");
614
+ if (fs.existsSync(sharedDir) && !fs.existsSync(targetSharedDir)) {
615
+ fs.cpSync(sharedDir, targetSharedDir, { recursive: true });
616
+ sharedInstalled = true;
617
+ }
618
+ } catch (copyErr) {
619
+ step(c.yellow(`Warning: Some files failed to copy: ${copyErr.message}`), S.diamond, "yellow");
620
+ if (process.env.DEBUG) console.error(copyErr.stack);
573
621
  }
574
622
 
575
623
  // Install PikaKit Engine Extension (if user chose yes earlier)
@@ -676,4 +724,7 @@ export async function run(spec) {
676
724
  }
677
725
  ).split("\n").map(l => `${c.gray(S.branch)} ${l}`).join("\n"));
678
726
  step(`${c.green("✓")} ${c.bold("Installation Complete!")}`);
727
+
728
+ // Clear global timeout
729
+ clearTimeout(globalTimer);
679
730
  }
package/bin/lib/ui.js CHANGED
@@ -154,6 +154,9 @@ export function brandedIntro(version, status = "") {
154
154
  // Split banner and filter to get content lines only
155
155
  const bannerLines = PIKAKIT_BANNER.split('\n').filter(line => line.trim() !== '');
156
156
 
157
+ // Add spacing from terminal prompt
158
+ console.log('');
159
+
157
160
  // Print all banner lines with gradient
158
161
  for (const line of bannerLines) {
159
162
  console.log(pikaGradient(line));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pikakit",
3
- "version": "3.9.102",
3
+ "version": "3.9.104",
4
4
  "description": "PikaKit — Install 51 skills, 18 workflows, 21 agents into your AI project. One command.",
5
5
  "license": "MIT",
6
6
  "author": "pikakit <pikakit@gmail.com>",