skill-master 0.1.0 → 0.1.2

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
@@ -1,6 +1,6 @@
1
1
  # skill-master
2
2
 
3
- [中文文档](./README.zh-CN.md)
3
+ English | [简体中文](./README.zh-CN.md)
4
4
 
5
5
  Cross-platform skill package manager for AI coding agents, fully compatible with `npx skills` CLI.
6
6
 
package/README.zh-CN.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # skill-master
2
2
 
3
+ [English](./README.md) | 简体中文
4
+
3
5
  跨平台 Skill 包管理器,解决 `npx skills` 的两大核心问题:
4
6
 
5
7
  1. **保护 .env 配置** — 安装/更新时自动备份和恢复环境变量,不再丢失 API Key
package/dist/cli.js CHANGED
@@ -153,7 +153,7 @@ function tableRow(...cols) {
153
153
  // src/core/git-source.ts
154
154
  var execFileAsync = promisify(execFile);
155
155
  function isGitUrl(source) {
156
- return source.startsWith("https://") || source.startsWith("http://") || source.startsWith("git@") || source.startsWith("git://") || source.includes("github.com/") || source.includes("gitlab.com/");
156
+ return source.startsWith("https://") || source.startsWith("http://") || source.startsWith("git@") || source.startsWith("git://") || source.includes("github.com/") || source.includes("gitlab.com/") || /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+$/.test(source);
157
157
  }
158
158
  function normalizeGitUrl(source) {
159
159
  if (source.startsWith("https://") || source.startsWith("http://") || source.startsWith("git@") || source.startsWith("git://")) {
@@ -297,30 +297,310 @@ function extractEnvKeys(envExampleContent) {
297
297
  }
298
298
 
299
299
  // src/core/env-manager.ts
300
- import { join as join4 } from "path";
300
+ import { join as join5 } from "path";
301
301
 
302
302
  // src/utils/paths.ts
303
- import { homedir } from "os";
303
+ import { homedir as homedir2 } from "os";
304
+ import { join as join4 } from "path";
305
+
306
+ // src/platform/agents.ts
307
+ import { existsSync as existsSync4 } from "fs";
304
308
  import { join as join3 } from "path";
305
- var AGENTS_HOME = join3(homedir(), ".agents");
306
- var CONFIG_DIR = join3(AGENTS_HOME, "config");
307
- var SKILLS_DIR = join3(AGENTS_HOME, "skills");
308
- var REGISTRY_PATH = join3(AGENTS_HOME, "registry.json");
309
+ import { homedir } from "os";
310
+ var home = homedir();
311
+ var configHome = process.env.XDG_CONFIG_HOME?.trim() || join3(home, ".config");
312
+ var codexHome = process.env.CODEX_HOME?.trim() || join3(home, ".codex");
313
+ var claudeHome = process.env.CLAUDE_CONFIG_DIR?.trim() || join3(home, ".claude");
314
+ var AGENTS = {
315
+ amp: {
316
+ name: "amp",
317
+ displayName: "Amp",
318
+ skillsDir: ".agents/skills",
319
+ globalSkillsDir: join3(configHome, "agents/skills")
320
+ },
321
+ antigravity: {
322
+ name: "antigravity",
323
+ displayName: "Antigravity",
324
+ skillsDir: ".agent/skills",
325
+ globalSkillsDir: join3(home, ".gemini/antigravity/skills"),
326
+ detectMarker: ".agent"
327
+ },
328
+ augment: {
329
+ name: "augment",
330
+ displayName: "Augment",
331
+ skillsDir: ".augment/skills",
332
+ globalSkillsDir: join3(home, ".augment/skills"),
333
+ detectMarker: ".augment"
334
+ },
335
+ "claude-code": {
336
+ name: "claude-code",
337
+ displayName: "Claude Code",
338
+ skillsDir: ".claude/skills",
339
+ globalSkillsDir: join3(claudeHome, "skills"),
340
+ detectMarker: ".claude"
341
+ },
342
+ openclaw: {
343
+ name: "openclaw",
344
+ displayName: "OpenClaw",
345
+ skillsDir: "skills",
346
+ globalSkillsDir: join3(home, ".openclaw/skills")
347
+ },
348
+ cline: {
349
+ name: "cline",
350
+ displayName: "Cline",
351
+ skillsDir: ".cline/skills",
352
+ globalSkillsDir: join3(home, ".cline/skills"),
353
+ detectMarker: ".cline"
354
+ },
355
+ codebuddy: {
356
+ name: "codebuddy",
357
+ displayName: "CodeBuddy",
358
+ skillsDir: ".codebuddy/skills",
359
+ globalSkillsDir: join3(home, ".codebuddy/skills"),
360
+ detectMarker: ".codebuddy"
361
+ },
362
+ codex: {
363
+ name: "codex",
364
+ displayName: "Codex",
365
+ skillsDir: ".agents/skills",
366
+ globalSkillsDir: join3(codexHome, "skills")
367
+ },
368
+ "command-code": {
369
+ name: "command-code",
370
+ displayName: "Command Code",
371
+ skillsDir: ".commandcode/skills",
372
+ globalSkillsDir: join3(home, ".commandcode/skills"),
373
+ detectMarker: ".commandcode"
374
+ },
375
+ continue: {
376
+ name: "continue",
377
+ displayName: "Continue",
378
+ skillsDir: ".continue/skills",
379
+ globalSkillsDir: join3(home, ".continue/skills"),
380
+ detectMarker: ".continue"
381
+ },
382
+ crush: {
383
+ name: "crush",
384
+ displayName: "Crush",
385
+ skillsDir: ".crush/skills",
386
+ globalSkillsDir: join3(home, ".config/crush/skills")
387
+ },
388
+ cursor: {
389
+ name: "cursor",
390
+ displayName: "Cursor",
391
+ skillsDir: ".cursor/skills",
392
+ globalSkillsDir: join3(home, ".cursor/skills"),
393
+ detectMarker: ".cursor"
394
+ },
395
+ droid: {
396
+ name: "droid",
397
+ displayName: "Droid",
398
+ skillsDir: ".factory/skills",
399
+ globalSkillsDir: join3(home, ".factory/skills"),
400
+ detectMarker: ".factory"
401
+ },
402
+ "gemini-cli": {
403
+ name: "gemini-cli",
404
+ displayName: "Gemini CLI",
405
+ skillsDir: ".agents/skills",
406
+ globalSkillsDir: join3(home, ".gemini/skills")
407
+ },
408
+ "github-copilot": {
409
+ name: "github-copilot",
410
+ displayName: "GitHub Copilot",
411
+ skillsDir: ".agents/skills",
412
+ globalSkillsDir: join3(home, ".copilot/skills")
413
+ },
414
+ goose: {
415
+ name: "goose",
416
+ displayName: "Goose",
417
+ skillsDir: ".goose/skills",
418
+ globalSkillsDir: join3(configHome, "goose/skills"),
419
+ detectMarker: ".goose"
420
+ },
421
+ junie: {
422
+ name: "junie",
423
+ displayName: "Junie",
424
+ skillsDir: ".junie/skills",
425
+ globalSkillsDir: join3(home, ".junie/skills"),
426
+ detectMarker: ".junie"
427
+ },
428
+ "iflow-cli": {
429
+ name: "iflow-cli",
430
+ displayName: "iFlow CLI",
431
+ skillsDir: ".iflow/skills",
432
+ globalSkillsDir: join3(home, ".iflow/skills"),
433
+ detectMarker: ".iflow"
434
+ },
435
+ kilo: {
436
+ name: "kilo",
437
+ displayName: "Kilo Code",
438
+ skillsDir: ".kilocode/skills",
439
+ globalSkillsDir: join3(home, ".kilocode/skills"),
440
+ detectMarker: ".kilocode"
441
+ },
442
+ "kimi-cli": {
443
+ name: "kimi-cli",
444
+ displayName: "Kimi Code CLI",
445
+ skillsDir: ".agents/skills",
446
+ globalSkillsDir: join3(home, ".config/agents/skills")
447
+ },
448
+ "kiro-cli": {
449
+ name: "kiro-cli",
450
+ displayName: "Kiro CLI",
451
+ skillsDir: ".kiro/skills",
452
+ globalSkillsDir: join3(home, ".kiro/skills"),
453
+ detectMarker: ".kiro"
454
+ },
455
+ kode: {
456
+ name: "kode",
457
+ displayName: "Kode",
458
+ skillsDir: ".kode/skills",
459
+ globalSkillsDir: join3(home, ".kode/skills"),
460
+ detectMarker: ".kode"
461
+ },
462
+ mcpjam: {
463
+ name: "mcpjam",
464
+ displayName: "MCPJam",
465
+ skillsDir: ".mcpjam/skills",
466
+ globalSkillsDir: join3(home, ".mcpjam/skills"),
467
+ detectMarker: ".mcpjam"
468
+ },
469
+ "mistral-vibe": {
470
+ name: "mistral-vibe",
471
+ displayName: "Mistral Vibe",
472
+ skillsDir: ".vibe/skills",
473
+ globalSkillsDir: join3(home, ".vibe/skills"),
474
+ detectMarker: ".vibe"
475
+ },
476
+ mux: {
477
+ name: "mux",
478
+ displayName: "Mux",
479
+ skillsDir: ".mux/skills",
480
+ globalSkillsDir: join3(home, ".mux/skills"),
481
+ detectMarker: ".mux"
482
+ },
483
+ opencode: {
484
+ name: "opencode",
485
+ displayName: "OpenCode",
486
+ skillsDir: ".opencode/skills",
487
+ globalSkillsDir: join3(configHome, "opencode/skills")
488
+ },
489
+ openhands: {
490
+ name: "openhands",
491
+ displayName: "OpenHands",
492
+ skillsDir: ".openhands/skills",
493
+ globalSkillsDir: join3(home, ".openhands/skills"),
494
+ detectMarker: ".openhands"
495
+ },
496
+ pi: {
497
+ name: "pi",
498
+ displayName: "Pi",
499
+ skillsDir: ".pi/skills",
500
+ globalSkillsDir: join3(home, ".pi/agent/skills"),
501
+ detectMarker: ".pi"
502
+ },
503
+ qoder: {
504
+ name: "qoder",
505
+ displayName: "Qoder",
506
+ skillsDir: ".qoder/skills",
507
+ globalSkillsDir: join3(home, ".qoder/skills"),
508
+ detectMarker: ".qoder"
509
+ },
510
+ "qwen-code": {
511
+ name: "qwen-code",
512
+ displayName: "Qwen Code",
513
+ skillsDir: ".qwen/skills",
514
+ globalSkillsDir: join3(home, ".qwen/skills"),
515
+ detectMarker: ".qwen"
516
+ },
517
+ replit: {
518
+ name: "replit",
519
+ displayName: "Replit",
520
+ skillsDir: ".agents/skills",
521
+ globalSkillsDir: join3(configHome, "agents/skills")
522
+ },
523
+ roo: {
524
+ name: "roo",
525
+ displayName: "Roo Code",
526
+ skillsDir: ".roo/skills",
527
+ globalSkillsDir: join3(home, ".roo/skills"),
528
+ detectMarker: ".roo"
529
+ },
530
+ trae: {
531
+ name: "trae",
532
+ displayName: "Trae",
533
+ skillsDir: ".trae/skills",
534
+ globalSkillsDir: join3(home, ".trae/skills"),
535
+ detectMarker: ".trae"
536
+ },
537
+ "trae-cn": {
538
+ name: "trae-cn",
539
+ displayName: "Trae CN",
540
+ skillsDir: ".trae/skills",
541
+ globalSkillsDir: join3(home, ".trae-cn/skills")
542
+ },
543
+ windsurf: {
544
+ name: "windsurf",
545
+ displayName: "Windsurf",
546
+ skillsDir: ".windsurf/skills",
547
+ globalSkillsDir: join3(home, ".codeium/windsurf/skills"),
548
+ detectMarker: ".windsurf"
549
+ },
550
+ zencoder: {
551
+ name: "zencoder",
552
+ displayName: "Zencoder",
553
+ skillsDir: ".zencoder/skills",
554
+ globalSkillsDir: join3(home, ".zencoder/skills"),
555
+ detectMarker: ".zencoder"
556
+ },
557
+ neovate: {
558
+ name: "neovate",
559
+ displayName: "Neovate",
560
+ skillsDir: ".neovate/skills",
561
+ globalSkillsDir: join3(home, ".neovate/skills"),
562
+ detectMarker: ".neovate"
563
+ },
564
+ pochi: {
565
+ name: "pochi",
566
+ displayName: "Pochi",
567
+ skillsDir: ".pochi/skills",
568
+ globalSkillsDir: join3(home, ".pochi/skills"),
569
+ detectMarker: ".pochi"
570
+ },
571
+ adal: {
572
+ name: "adal",
573
+ displayName: "AdaL",
574
+ skillsDir: ".adal/skills",
575
+ globalSkillsDir: join3(home, ".adal/skills"),
576
+ detectMarker: ".adal"
577
+ }
578
+ };
579
+ function detectPlatform(cwd) {
580
+ for (const [key, config] of Object.entries(AGENTS)) {
581
+ if (config.detectMarker && existsSync4(join3(cwd, config.detectMarker))) {
582
+ return key;
583
+ }
584
+ }
585
+ if (existsSync4(join3(configHome, "opencode"))) {
586
+ return "opencode";
587
+ }
588
+ return "claude-code";
589
+ }
590
+ function getAgentSkillPath(cwd, agent, name) {
591
+ return join3(cwd, AGENTS[agent].skillsDir, name);
592
+ }
593
+
594
+ // src/utils/paths.ts
595
+ var AGENTS_HOME = join4(homedir2(), ".agents");
596
+ var CONFIG_DIR = join4(AGENTS_HOME, "config");
597
+ var SKILLS_DIR = join4(AGENTS_HOME, "skills");
598
+ var REGISTRY_PATH = join4(AGENTS_HOME, "registry.json");
309
599
  function getSkillCanonicalPath(name) {
310
- return join3(SKILLS_DIR, name);
600
+ return join4(SKILLS_DIR, name);
311
601
  }
312
602
  function getSkillConfigPath(name) {
313
- return join3(CONFIG_DIR, name);
314
- }
315
- var AGENT_SKILL_DIRS = {
316
- "claude-code": ".claude/skills",
317
- "opencode": ".opencode/skills",
318
- "cursor": ".cursor/skills",
319
- "cline": ".cline/skills",
320
- "windsurf": ".windsurf/skills"
321
- };
322
- function getAgentSkillPath(cwd, agent, name) {
323
- return join3(cwd, AGENT_SKILL_DIRS[agent], name);
603
+ return join4(CONFIG_DIR, name);
324
604
  }
325
605
 
326
606
  // src/core/env-manager.ts
@@ -345,9 +625,9 @@ function serializeEnv(data) {
345
625
  }
346
626
  async function backupEnv(skillName, agentSkillDir) {
347
627
  const locations = [
348
- join4(getSkillConfigPath(skillName), ".env"),
349
- ...agentSkillDir ? [join4(agentSkillDir, ".env")] : [],
350
- join4(getSkillCanonicalPath(skillName), ".env")
628
+ join5(getSkillConfigPath(skillName), ".env"),
629
+ ...agentSkillDir ? [join5(agentSkillDir, ".env")] : [],
630
+ join5(getSkillCanonicalPath(skillName), ".env")
351
631
  ];
352
632
  for (const loc of locations) {
353
633
  const content = await readTextSafe(loc);
@@ -362,16 +642,16 @@ async function backupEnv(skillName, agentSkillDir) {
362
642
  return null;
363
643
  }
364
644
  async function restoreEnv(skillName, envData, skillDir) {
365
- const exampleContent = await readTextSafe(join4(skillDir, ".env.example"));
645
+ const exampleContent = await readTextSafe(join5(skillDir, ".env.example"));
366
646
  let finalContent;
367
647
  if (exampleContent) {
368
648
  finalContent = mergeEnv(envData, exampleContent);
369
649
  } else {
370
650
  finalContent = serializeEnv(envData);
371
651
  }
372
- const configEnvPath = join4(getSkillConfigPath(skillName), ".env");
652
+ const configEnvPath = join5(getSkillConfigPath(skillName), ".env");
373
653
  await writeText(configEnvPath, finalContent);
374
- const skillEnvPath = join4(skillDir, ".env");
654
+ const skillEnvPath = join5(skillDir, ".env");
375
655
  await writeText(skillEnvPath, finalContent);
376
656
  debug(`Restored .env to ${configEnvPath} and ${skillEnvPath}`);
377
657
  }
@@ -395,7 +675,7 @@ function mergeEnv(existing, exampleContent) {
395
675
  }
396
676
  async function getEnvStatus(skillName, requiredKeys) {
397
677
  if (requiredKeys.length === 0) return "configured";
398
- const configEnvPath = join4(getSkillConfigPath(skillName), ".env");
678
+ const configEnvPath = join5(getSkillConfigPath(skillName), ".env");
399
679
  const content = await readTextSafe(configEnvPath);
400
680
  if (!content) return "missing";
401
681
  const data = parseEnvFile(content);
@@ -407,22 +687,22 @@ async function getEnvStatus(skillName, requiredKeys) {
407
687
  return "missing";
408
688
  }
409
689
  async function setEnvValue(skillName, key, value, skillDir) {
410
- const configEnvPath = join4(getSkillConfigPath(skillName), ".env");
690
+ const configEnvPath = join5(getSkillConfigPath(skillName), ".env");
411
691
  const content = await readTextSafe(configEnvPath);
412
692
  const data = content ? parseEnvFile(content) : {};
413
693
  data[key] = value;
414
694
  const newContent = serializeEnv(data);
415
695
  await writeText(configEnvPath, newContent);
416
696
  if (skillDir) {
417
- await writeText(join4(skillDir, ".env"), newContent);
697
+ await writeText(join5(skillDir, ".env"), newContent);
418
698
  }
419
699
  }
420
700
  function getEnvEditPath(skillName) {
421
- return join4(getSkillConfigPath(skillName), ".env");
701
+ return join5(getSkillConfigPath(skillName), ".env");
422
702
  }
423
703
 
424
704
  // src/core/registry.ts
425
- import { existsSync as existsSync4 } from "fs";
705
+ import { existsSync as existsSync5 } from "fs";
426
706
  function createEmptyRegistry() {
427
707
  return { version: 1, skills: {} };
428
708
  }
@@ -432,7 +712,7 @@ function validateRegistry(data) {
432
712
  return reg.version === 1 && typeof reg.skills === "object" && reg.skills !== null;
433
713
  }
434
714
  async function readRegistry() {
435
- if (!existsSync4(REGISTRY_PATH)) {
715
+ if (!existsSync5(REGISTRY_PATH)) {
436
716
  return createEmptyRegistry();
437
717
  }
438
718
  const data = await readJsonSafe(REGISTRY_PATH);
@@ -463,28 +743,6 @@ async function getRegistryEntry(skillName) {
463
743
  return registry.skills[skillName] ?? null;
464
744
  }
465
745
 
466
- // src/platform/detector.ts
467
- import { existsSync as existsSync5 } from "fs";
468
- import { join as join5 } from "path";
469
- import { homedir as homedir2 } from "os";
470
- var PLATFORM_MARKERS = [
471
- { dir: ".claude", platform: "claude-code" },
472
- { dir: ".cursor", platform: "cursor" },
473
- { dir: ".windsurf", platform: "windsurf" },
474
- { dir: ".cline", platform: "cline" }
475
- ];
476
- function detectPlatform(cwd) {
477
- for (const { dir, platform } of PLATFORM_MARKERS) {
478
- if (existsSync5(join5(cwd, dir))) {
479
- return platform;
480
- }
481
- }
482
- if (existsSync5(join5(homedir2(), ".config", "opencode"))) {
483
- return "opencode";
484
- }
485
- return "claude-code";
486
- }
487
-
488
746
  // src/core/installer.ts
489
747
  var TOTAL_STEPS = 9;
490
748
  async function installSkill(options) {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/installer.ts","../src/core/git-source.ts","../src/utils/fs-helpers.ts","../src/utils/errors.ts","../src/utils/logger.ts","../src/core/skill-parser.ts","../src/core/env-manager.ts","../src/utils/paths.ts","../src/core/registry.ts","../src/platform/detector.ts","../src/commands/add.ts","../src/commands/update.ts","../src/commands/remove.ts","../src/commands/env.ts","../src/commands/list.ts","../src/commands/info.ts","../src/commands/doctor.ts","../src/commands/find.ts","../src/commands/init.ts","../src/commands/check.ts","../src/cli.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { cloneRepo, isGitUrl, isLocalPath } from './git-source.js';\nimport { findSkillDirectory, readSkillMd, inferCapabilities, extractEnvKeys } from './skill-parser.js';\nimport { backupEnv, restoreEnv } from './env-manager.js';\nimport { updateRegistry } from './registry.js';\nimport { detectPlatform, getAgentSkillsDir } from '../platform/detector.js';\nimport { copyDir, removePath, symlinkOrCopy, ensureDir, readTextSafe } from '../utils/fs-helpers.js';\nimport { getSkillCanonicalPath, getAgentSkillPath } from '../utils/paths.js';\nimport * as logger from '../utils/logger.js';\nimport { SkillNotFoundError, SkillParseError } from '../utils/errors.js';\nimport type { InstallOptions, RegistryEntry } from '../types/index.js';\n\nconst TOTAL_STEPS = 9;\n\n/**\n * Main installation engine — 9-step process:\n * 1. fetchSource → clone/copy to temp\n * 2. findSkillDir → locate SKILL.md\n * 3. parseSkillMd → parse frontmatter\n * 4. detectAgent → determine target platform\n * 5. backupEnv → preserve existing .env\n * 6. cleanAndInstall → rm old → copy new to canonical\n * 7. restoreEnv → restore .env to both locations\n * 8. linkOrCopy → symlink/copy to agent dir\n * 9. updateRegistry → update registry.json\n */\nexport async function installSkill(options: InstallOptions): Promise<void> {\n const { source, cwd, copy = false, force = false } = options;\n\n // Step 1: Fetch source\n logger.step(1, TOTAL_STEPS, 'Fetching skill source...');\n let sourceDir: string;\n\n if (source.type === 'git') {\n sourceDir = await cloneRepo(source.url!, source.branch);\n } else if (source.type === 'local') {\n sourceDir = source.path!;\n if (!existsSync(sourceDir)) {\n throw new SkillNotFoundError(sourceDir);\n }\n } else {\n throw new SkillParseError('Invalid source type');\n }\n\n // Step 2: Find skill directory\n logger.step(2, TOTAL_STEPS, 'Locating SKILL.md...');\n const skillDir = await findSkillDirectory(sourceDir);\n if (!skillDir) {\n throw new SkillNotFoundError(`No SKILL.md found in ${sourceDir}`);\n }\n\n // Step 3: Parse SKILL.md\n logger.step(3, TOTAL_STEPS, 'Parsing SKILL.md...');\n const parsed = await readSkillMd(skillDir);\n if (!parsed) {\n throw new SkillParseError('Failed to read SKILL.md');\n }\n const skillName = parsed.frontmatter.name;\n logger.info(`Found skill: ${skillName} v${parsed.frontmatter.version}`);\n\n // Step 4: Detect agent platform\n logger.step(4, TOTAL_STEPS, 'Detecting agent platform...');\n const agent = options.agent ?? detectPlatform(cwd);\n logger.info(`Target platform: ${agent}`);\n\n // Step 5: Backup existing .env\n logger.step(5, TOTAL_STEPS, 'Backing up .env...');\n const agentSkillDir = getAgentSkillPath(cwd, agent, skillName);\n const envBackup = await backupEnv(skillName, agentSkillDir);\n if (envBackup) {\n logger.success(`Backed up ${Object.keys(envBackup).length} env key(s)`);\n } else {\n logger.info('No existing .env found');\n }\n\n // Step 6: Clean and install to canonical path\n logger.step(6, TOTAL_STEPS, 'Installing to canonical path...');\n const canonicalPath = getSkillCanonicalPath(skillName);\n\n if (existsSync(canonicalPath) && !force) {\n logger.info('Replacing existing installation');\n }\n await removePath(canonicalPath);\n await copyDir(skillDir, canonicalPath);\n logger.success(`Installed to ${canonicalPath}`);\n\n // Step 7: Restore .env\n logger.step(7, TOTAL_STEPS, 'Restoring .env...');\n if (envBackup) {\n await restoreEnv(skillName, envBackup, canonicalPath);\n logger.success('.env restored successfully');\n } else {\n // Check if there's a .env.example to hint about\n const examplePath = join(canonicalPath, '.env.example');\n if (existsSync(examplePath)) {\n logger.warn('Found .env.example — run `skill-master env edit ' + skillName + '` to configure');\n }\n }\n\n // Step 8: Link or copy to agent directory\n logger.step(8, TOTAL_STEPS, `Linking to ${agent} skills directory...`);\n const agentPath = getAgentSkillPath(cwd, agent, skillName);\n const linkType = await symlinkOrCopy(canonicalPath, agentPath, copy);\n logger.success(`${linkType === 'symlink' ? 'Symlinked' : 'Copied'} to ${agentPath}`);\n\n // Step 9: Update registry\n logger.step(9, TOTAL_STEPS, 'Updating registry...');\n const capabilities = parsed.frontmatter.capabilities ?? inferCapabilities(parsed.frontmatter['allowed-tools']);\n\n // Extract env keys from .env.example\n const envExampleContent = await readTextSafe(join(canonicalPath, '.env.example'));\n const envKeys = envExampleContent ? extractEnvKeys(envExampleContent) : [];\n\n const now = new Date().toISOString();\n const entry: RegistryEntry = {\n source: source.type === 'git' ? source.url! : source.path!,\n version: parsed.frontmatter.version,\n installed_at: now,\n updated_at: now,\n agent,\n env_keys: envKeys,\n capabilities,\n canonical_path: canonicalPath,\n agent_path: agentPath,\n };\n\n await updateRegistry(skillName, entry);\n logger.blank();\n logger.success(`Skill \"${skillName}\" installed successfully!`);\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { existsSync } from 'node:fs';\nimport { ensureDir, createTempDir } from '../utils/fs-helpers.js';\nimport { GitCloneError } from '../utils/errors.js';\nimport * as logger from '../utils/logger.js';\n\nconst execFileAsync = promisify(execFile);\n\n/** Check if a string looks like a git URL */\nexport function isGitUrl(source: string): boolean {\n return (\n source.startsWith('https://') ||\n source.startsWith('http://') ||\n source.startsWith('git@') ||\n source.startsWith('git://') ||\n source.includes('github.com/') ||\n source.includes('gitlab.com/')\n );\n}\n\n/** Normalize a GitHub shorthand or URL to a full clone URL */\nexport function normalizeGitUrl(source: string): string {\n // Already a full URL\n if (source.startsWith('https://') || source.startsWith('http://') ||\n source.startsWith('git@') || source.startsWith('git://')) {\n // Ensure .git suffix for HTTPS URLs\n if (source.startsWith('https://') && !source.endsWith('.git')) {\n return source + '.git';\n }\n return source;\n }\n\n // GitHub shorthand: owner/repo\n if (/^[a-zA-Z0-9_.-]+\\/[a-zA-Z0-9_.-]+$/.test(source)) {\n return `https://github.com/${source}.git`;\n }\n\n return source;\n}\n\n/** Parse a GitHub URL into owner and repo */\nexport function parseGitUrl(url: string): { owner: string; repo: string; branch?: string } {\n // Handle tree/branch in URL: github.com/owner/repo/tree/branch\n const treeMatch = url.match(/github\\.com\\/([^/]+)\\/([^/]+)\\/tree\\/(.+)/);\n if (treeMatch) {\n return {\n owner: treeMatch[1],\n repo: treeMatch[2].replace(/\\.git$/, ''),\n branch: treeMatch[3],\n };\n }\n\n // Standard URL: github.com/owner/repo\n const match = url.match(/github\\.com[/:]([^/]+)\\/([^/.]+)/);\n if (match) {\n return { owner: match[1], repo: match[2] };\n }\n\n throw new GitCloneError(url, 'Unable to parse GitHub URL');\n}\n\n/** Clone a git repository to a temporary directory */\nexport async function cloneRepo(\n url: string,\n branch?: string,\n): Promise<string> {\n const normalizedUrl = normalizeGitUrl(url);\n const tempDir = createTempDir();\n await ensureDir(tempDir);\n\n const args = ['clone', '--depth', '1'];\n if (branch) {\n args.push('--branch', branch);\n }\n args.push(normalizedUrl, tempDir);\n\n logger.debug(`Cloning ${normalizedUrl} to ${tempDir}`);\n\n try {\n await execFileAsync('git', args, { timeout: 60_000 });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new GitCloneError(url, msg);\n }\n\n return tempDir;\n}\n\n/** Check if a local path exists and contains a skill */\nexport function isLocalPath(source: string): boolean {\n return existsSync(source);\n}","import { mkdir, cp, readFile, writeFile, rename, symlink, lstat, rm } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { tmpdir } from 'node:os';\nimport { randomBytes } from 'node:crypto';\n\n/** Ensure a directory exists (recursive) */\nexport async function ensureDir(dir: string): Promise<void> {\n await mkdir(dir, { recursive: true });\n}\n\n/** Recursively copy a directory */\nexport async function copyDir(src: string, dest: string): Promise<void> {\n await ensureDir(dest);\n await cp(src, dest, { recursive: true, force: true });\n}\n\n/** Remove a directory or file recursively */\nexport async function removePath(target: string): Promise<void> {\n if (existsSync(target)) {\n await rm(target, { recursive: true, force: true });\n }\n}\n\n/** Atomic JSON write: write to .tmp then rename */\nexport async function atomicWriteJson(filePath: string, data: unknown): Promise<void> {\n await ensureDir(dirname(filePath));\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, JSON.stringify(data, null, 2) + '\\n', 'utf-8');\n await rename(tmpPath, filePath);\n}\n\n/** Safely read and parse a JSON file, return null on failure */\nexport async function readJsonSafe<T>(filePath: string): Promise<T | null> {\n try {\n const content = await readFile(filePath, 'utf-8');\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\n/** Read a text file, return null if not found */\nexport async function readTextSafe(filePath: string): Promise<string | null> {\n try {\n return await readFile(filePath, 'utf-8');\n } catch {\n return null;\n }\n}\n\n/** Write text to a file, ensuring parent directory exists */\nexport async function writeText(filePath: string, content: string): Promise<void> {\n await ensureDir(dirname(filePath));\n await writeFile(filePath, content, 'utf-8');\n}\n\n/** Create a symlink, or copy if symlink fails (Windows fallback) */\nexport async function symlinkOrCopy(target: string, linkPath: string, forceCopy = false): Promise<'symlink' | 'copy'> {\n await ensureDir(dirname(linkPath));\n\n // Remove existing link/dir\n await removePath(linkPath);\n\n if (forceCopy) {\n await copyDir(target, linkPath);\n return 'copy';\n }\n\n try {\n await symlink(target, linkPath, 'dir');\n return 'symlink';\n } catch {\n // Fallback to copy on platforms that don't support symlinks\n await copyDir(target, linkPath);\n return 'copy';\n }\n}\n\n/** Check if a path is a symlink */\nexport async function isSymlink(path: string): Promise<boolean> {\n try {\n const stat = await lstat(path);\n return stat.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/** Create a temporary directory with a unique name */\nexport function createTempDir(): string {\n const id = randomBytes(8).toString('hex');\n return join(tmpdir(), `skill-master-${id}`);\n}\n","/** Base error class for skill-master */\nexport class SkillManagerError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SkillManagerError';\n }\n}\n\n/** Skill not found in registry or filesystem */\nexport class SkillNotFoundError extends SkillManagerError {\n constructor(skillName: string) {\n super(`Skill \"${skillName}\" not found`);\n this.name = 'SkillNotFoundError';\n }\n}\n\n/** Required .env key is missing */\nexport class EnvMissingError extends SkillManagerError {\n constructor(skillName: string, keys: string[]) {\n super(`Skill \"${skillName}\" is missing env keys: ${keys.join(', ')}`);\n this.name = 'EnvMissingError';\n }\n}\n\n/** Registry file is corrupted or invalid */\nexport class RegistryCorruptError extends SkillManagerError {\n constructor(detail?: string) {\n super(`Registry is corrupted${detail ? ': ' + detail : ''}`);\n this.name = 'RegistryCorruptError';\n }\n}\n\n/** Git clone operation failed */\nexport class GitCloneError extends SkillManagerError {\n constructor(url: string, detail?: string) {\n super(`Failed to clone \"${url}\"${detail ? ': ' + detail : ''}`);\n this.name = 'GitCloneError';\n }\n}\n\n/** SKILL.md parsing or validation failed */\nexport class SkillParseError extends SkillManagerError {\n constructor(detail: string) {\n super(`Failed to parse SKILL.md: ${detail}`);\n this.name = 'SkillParseError';\n }\n}\n\n/** Platform detection failed or unsupported */\nexport class PlatformError extends SkillManagerError {\n constructor(detail: string) {\n super(`Platform error: ${detail}`);\n this.name = 'PlatformError';\n }\n}\n","import chalk from 'chalk';\n\nconst PREFIX = chalk.blue('skill-master');\n\n/** Informational message */\nexport function info(msg: string): void {\n console.log(`${PREFIX} ${chalk.cyan('info')} ${msg}`);\n}\n\n/** Success message */\nexport function success(msg: string): void {\n console.log(`${PREFIX} ${chalk.green('✔')} ${msg}`);\n}\n\n/** Warning message */\nexport function warn(msg: string): void {\n console.log(`${PREFIX} ${chalk.yellow('⚠')} ${msg}`);\n}\n\n/** Error message */\nexport function error(msg: string): void {\n console.error(`${PREFIX} ${chalk.red('✖')} ${msg}`);\n}\n\n/** Debug message (only when DEBUG env is set) */\nexport function debug(msg: string): void {\n if (process.env.DEBUG) {\n console.log(`${PREFIX} ${chalk.gray('debug')} ${msg}`);\n }\n}\n\n/** Step indicator with number */\nexport function step(num: number, total: number, msg: string): void {\n const counter = chalk.gray(`[${num}/${total}]`);\n console.log(`${PREFIX} ${counter} ${msg}`);\n}\n\n/** Print a blank line */\nexport function blank(): void {\n console.log();\n}\n\n/** Print a key-value pair */\nexport function kv(key: string, value: string): void {\n console.log(` ${chalk.gray(key + ':')} ${value}`);\n}\n\n/** Print a table header */\nexport function tableHeader(...cols: string[]): void {\n console.log(chalk.bold(cols.map(c => c.padEnd(20)).join('')));\n console.log(chalk.gray('─'.repeat(cols.length * 20)));\n}\n\n/** Print a table row */\nexport function tableRow(...cols: string[]): void {\n console.log(cols.map(c => c.padEnd(20)).join(''));\n}\n","import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport { readdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { readTextSafe } from '../utils/fs-helpers.js';\nimport { SkillParseError } from '../utils/errors.js';\nimport type { ParsedSkill, SkillFrontmatter, Capability } from '../types/index.js';\n\n/** Tool-to-capability reverse mapping for Claude Code tools */\nconst TOOL_CAPABILITY_MAP: Record<string, Capability> = {\n 'Bash': 'shell',\n 'Read': 'read_file',\n 'Write': 'write_file',\n 'Edit': 'edit_file',\n 'Glob': 'find_file',\n 'Grep': 'search_content',\n 'Task': 'sub_task',\n 'WebFetch': 'web_fetch',\n 'WebSearch': 'web_search',\n};\n\n/** Parse a SKILL.md file content into frontmatter + body */\nexport function parseSkillMd(content: string): ParsedSkill {\n const match = content.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n if (!match) {\n throw new SkillParseError('No valid frontmatter block found');\n }\n\n const rawFrontmatter = match[1];\n const body = match[2];\n\n let frontmatter: SkillFrontmatter;\n try {\n frontmatter = parseYaml(rawFrontmatter) as SkillFrontmatter;\n } catch (err) {\n throw new SkillParseError(`YAML parse error: ${(err as Error).message}`);\n }\n\n validateFrontmatter(frontmatter);\n\n return { frontmatter, body, rawFrontmatter };\n}\n\n/** Validate required frontmatter fields */\nexport function validateFrontmatter(fm: SkillFrontmatter): void {\n if (!fm.name || typeof fm.name !== 'string') {\n throw new SkillParseError('Missing or invalid \"name\" field');\n }\n if (!fm.version || typeof fm.version !== 'string') {\n throw new SkillParseError('Missing or invalid \"version\" field');\n }\n if (!Array.isArray(fm['allowed-tools']) || fm['allowed-tools'].length === 0) {\n throw new SkillParseError('Missing or empty \"allowed-tools\" field');\n }\n}\n\n/** Infer abstract capabilities from allowed-tools list */\nexport function inferCapabilities(allowedTools: string[]): Capability[] {\n const caps = new Set<Capability>();\n for (const tool of allowedTools) {\n const cap = TOOL_CAPABILITY_MAP[tool];\n if (cap) {\n caps.add(cap);\n }\n }\n return [...caps];\n}\n\n/** Serialize a ParsedSkill back to SKILL.md format */\nexport function serializeSkillMd(parsed: ParsedSkill): string {\n const yamlStr = stringifyYaml(parsed.frontmatter, { lineWidth: 0 }).trimEnd();\n return `---\\n${yamlStr}\\n---\\n${parsed.body}`;\n}\n\n/** Search for SKILL.md files within a directory (looks in .claude/skills/*) */\nexport async function findSkillDirectory(dir: string): Promise<string | null> {\n // Direct SKILL.md in root\n if (existsSync(join(dir, 'SKILL.md'))) {\n return dir;\n }\n\n // Search in .claude/skills/*/SKILL.md\n const skillsRoot = join(dir, '.claude', 'skills');\n if (!existsSync(skillsRoot)) {\n return null;\n }\n\n try {\n const entries = await readdir(skillsRoot, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const skillMdPath = join(skillsRoot, entry.name, 'SKILL.md');\n if (existsSync(skillMdPath)) {\n return join(skillsRoot, entry.name);\n }\n }\n }\n } catch {\n return null;\n }\n\n return null;\n}\n\n/** Read and parse a SKILL.md from a directory */\nexport async function readSkillMd(dir: string): Promise<ParsedSkill | null> {\n const content = await readTextSafe(join(dir, 'SKILL.md'));\n if (!content) return null;\n return parseSkillMd(content);\n}\n\n/** Extract env keys from a .env.example file */\nexport function extractEnvKeys(envExampleContent: string): string[] {\n const keys: string[] = [];\n for (const line of envExampleContent.split('\\n')) {\n const trimmed = line.trim();\n if (trimmed && !trimmed.startsWith('#')) {\n const match = trimmed.match(/^([A-Z_][A-Z0-9_]*)=/);\n if (match) {\n keys.push(match[1]);\n }\n }\n }\n return keys;\n}\n","import { join } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { readTextSafe, writeText, ensureDir } from '../utils/fs-helpers.js';\nimport { getSkillConfigPath, getSkillCanonicalPath } from '../utils/paths.js';\nimport * as logger from '../utils/logger.js';\nimport type { EnvStatus } from '../types/index.js';\n\n/** Parse a .env file content into key-value pairs */\nexport function parseEnvFile(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex === -1) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n // Strip surrounding quotes\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1);\n }\n result[key] = value;\n }\n return result;\n}\n\n/** Serialize key-value pairs back to .env format */\nexport function serializeEnv(data: Record<string, string>): string {\n return Object.entries(data)\n .map(([key, value]) => `${key}=${value}`)\n .join('\\n') + '\\n';\n}\n\n/**\n * Backup .env for a skill, searching multiple locations by priority:\n * 1. ~/.agents/config/<skill>/.env (persistent)\n * 2. agentSkillDir/.env (current agent dir, e.g. .claude/skills/<skill>)\n * 3. ~/.agents/skills/<skill>/.env (canonical)\n */\nexport async function backupEnv(\n skillName: string,\n agentSkillDir?: string,\n): Promise<Record<string, string> | null> {\n const locations = [\n join(getSkillConfigPath(skillName), '.env'),\n ...(agentSkillDir ? [join(agentSkillDir, '.env')] : []),\n join(getSkillCanonicalPath(skillName), '.env'),\n ];\n\n for (const loc of locations) {\n const content = await readTextSafe(loc);\n if (content) {\n const data = parseEnvFile(content);\n if (Object.keys(data).length > 0) {\n logger.debug(`Backed up .env from ${loc}`);\n return data;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Restore .env to both persistent and skill directory locations.\n * Merges with .env.example if present.\n */\nexport async function restoreEnv(\n skillName: string,\n envData: Record<string, string>,\n skillDir: string,\n): Promise<void> {\n // Read .env.example from skill dir if exists\n const exampleContent = await readTextSafe(join(skillDir, '.env.example'));\n let finalContent: string;\n\n if (exampleContent) {\n finalContent = mergeEnv(envData, exampleContent);\n } else {\n finalContent = serializeEnv(envData);\n }\n\n // Write to persistent config location\n const configEnvPath = join(getSkillConfigPath(skillName), '.env');\n await writeText(configEnvPath, finalContent);\n\n // Write to skill directory (for compatibility with loadApiKey)\n const skillEnvPath = join(skillDir, '.env');\n await writeText(skillEnvPath, finalContent);\n\n logger.debug(`Restored .env to ${configEnvPath} and ${skillEnvPath}`);\n}\n\n/**\n * Merge existing env data with .env.example template.\n * - Existing keys are NEVER overwritten\n * - New keys from example are appended with empty values and comments\n */\nexport function mergeEnv(\n existing: Record<string, string>,\n exampleContent: string,\n): string {\n const lines: string[] = [];\n const usedKeys = new Set<string>();\n\n // First, write all existing keys\n for (const [key, value] of Object.entries(existing)) {\n lines.push(`${key}=${value}`);\n usedKeys.add(key);\n }\n\n // Then, append new keys from example\n const exampleKeys = parseEnvFile(exampleContent);\n const newKeys = Object.keys(exampleKeys).filter(k => !usedKeys.has(k));\n\n if (newKeys.length > 0) {\n lines.push('');\n lines.push('# New keys added by skill update (please configure):');\n for (const key of newKeys) {\n lines.push(`# ${key}=`);\n }\n }\n\n return lines.join('\\n') + '\\n';\n}\n\n/** Check the .env configuration status for a skill */\nexport async function getEnvStatus(\n skillName: string,\n requiredKeys: string[],\n): Promise<EnvStatus> {\n if (requiredKeys.length === 0) return 'configured';\n\n const configEnvPath = join(getSkillConfigPath(skillName), '.env');\n const content = await readTextSafe(configEnvPath);\n\n if (!content) return 'missing';\n\n const data = parseEnvFile(content);\n const configuredKeys = Object.entries(data)\n .filter(([, v]) => v && !v.includes('your_') && !v.includes('_here'))\n .map(([k]) => k);\n\n const allConfigured = requiredKeys.every(k => configuredKeys.includes(k));\n const someConfigured = requiredKeys.some(k => configuredKeys.includes(k));\n\n if (allConfigured) return 'configured';\n if (someConfigured) return 'partial';\n return 'missing';\n}\n\n/** Set a single env value for a skill */\nexport async function setEnvValue(\n skillName: string,\n key: string,\n value: string,\n skillDir?: string,\n): Promise<void> {\n const configEnvPath = join(getSkillConfigPath(skillName), '.env');\n const content = await readTextSafe(configEnvPath);\n const data = content ? parseEnvFile(content) : {};\n\n data[key] = value;\n const newContent = serializeEnv(data);\n\n // Write to persistent location\n await writeText(configEnvPath, newContent);\n\n // Sync to skill directory if provided\n if (skillDir) {\n await writeText(join(skillDir, '.env'), newContent);\n }\n}\n\n/** Get the .env file path for editing */\nexport function getEnvEditPath(skillName: string): string {\n return join(getSkillConfigPath(skillName), '.env');\n}\n","import { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { AgentPlatform } from '../types/index.js';\n\n/** Root directory for all skill-master data */\nexport const AGENTS_HOME = join(homedir(), '.agents');\n\n/** Persistent user config (API keys etc.) */\nexport const CONFIG_DIR = join(AGENTS_HOME, 'config');\n\n/** Canonical skill code storage */\nexport const SKILLS_DIR = join(AGENTS_HOME, 'skills');\n\n/** Registry file path */\nexport const REGISTRY_PATH = join(AGENTS_HOME, 'registry.json');\n\n/** Get canonical path for a skill's code */\nexport function getSkillCanonicalPath(name: string): string {\n return join(SKILLS_DIR, name);\n}\n\n/** Get persistent config path for a skill (holds .env) */\nexport function getSkillConfigPath(name: string): string {\n return join(CONFIG_DIR, name);\n}\n\n/** Platform-specific skill directory mappings */\nconst AGENT_SKILL_DIRS: Record<AgentPlatform, string> = {\n 'claude-code': '.claude/skills',\n 'opencode': '.opencode/skills',\n 'cursor': '.cursor/skills',\n 'cline': '.cline/skills',\n 'windsurf': '.windsurf/skills',\n};\n\n/** Get the agent-specific skill installation path */\nexport function getAgentSkillPath(\n cwd: string,\n agent: AgentPlatform,\n name: string,\n): string {\n return join(cwd, AGENT_SKILL_DIRS[agent], name);\n}\n\n/** Get the agent skills root directory */\nexport function getAgentSkillsRoot(cwd: string, agent: AgentPlatform): string {\n return join(cwd, AGENT_SKILL_DIRS[agent]);\n}\n","import { existsSync } from 'node:fs';\nimport { REGISTRY_PATH } from '../utils/paths.js';\nimport { atomicWriteJson, readJsonSafe } from '../utils/fs-helpers.js';\nimport { RegistryCorruptError } from '../utils/errors.js';\nimport type { Registry, RegistryEntry } from '../types/index.js';\n\n/** Create an empty registry */\nfunction createEmptyRegistry(): Registry {\n return { version: 1, skills: {} };\n}\n\n/** Validate registry structure */\nfunction validateRegistry(data: unknown): data is Registry {\n if (!data || typeof data !== 'object') return false;\n const reg = data as Record<string, unknown>;\n return reg.version === 1 && typeof reg.skills === 'object' && reg.skills !== null;\n}\n\n/** Read the registry, creating a new one if it doesn't exist */\nexport async function readRegistry(): Promise<Registry> {\n if (!existsSync(REGISTRY_PATH)) {\n return createEmptyRegistry();\n }\n\n const data = await readJsonSafe<Registry>(REGISTRY_PATH);\n if (!data) {\n throw new RegistryCorruptError('Failed to parse registry.json');\n }\n\n if (!validateRegistry(data)) {\n throw new RegistryCorruptError('Invalid registry structure');\n }\n\n return data;\n}\n\n/** Update or add a skill entry in the registry (atomic write) */\nexport async function updateRegistry(\n skillName: string,\n entry: RegistryEntry,\n): Promise<void> {\n const registry = await readRegistry();\n registry.skills[skillName] = entry;\n await atomicWriteJson(REGISTRY_PATH, registry);\n}\n\n/** Remove a skill from the registry */\nexport async function removeFromRegistry(skillName: string): Promise<void> {\n const registry = await readRegistry();\n delete registry.skills[skillName];\n await atomicWriteJson(REGISTRY_PATH, registry);\n}\n\n/** List all registered skills */\nexport async function listRegistry(): Promise<Record<string, RegistryEntry>> {\n const registry = await readRegistry();\n return registry.skills;\n}\n\n/** Get a single registry entry */\nexport async function getRegistryEntry(skillName: string): Promise<RegistryEntry | null> {\n const registry = await readRegistry();\n return registry.skills[skillName] ?? null;\n}","import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { AgentPlatform } from '../types/index.js';\n\n/** Platform detection markers in order of priority */\nconst PLATFORM_MARKERS: Array<{ dir: string; platform: AgentPlatform }> = [\n { dir: '.claude', platform: 'claude-code' },\n { dir: '.cursor', platform: 'cursor' },\n { dir: '.windsurf', platform: 'windsurf' },\n { dir: '.cline', platform: 'cline' },\n];\n\n/**\n * Detect the agent platform based on directory markers in cwd.\n * Falls back to checking ~/.config/opencode, then defaults to claude-code.\n */\nexport function detectPlatform(cwd: string): AgentPlatform {\n for (const { dir, platform } of PLATFORM_MARKERS) {\n if (existsSync(join(cwd, dir))) {\n return platform;\n }\n }\n\n // Check for opencode\n if (existsSync(join(homedir(), '.config', 'opencode'))) {\n return 'opencode';\n }\n\n // Default\n return 'claude-code';\n}\n\n/** Agent-specific skills directory names */\nconst AGENT_SKILLS_DIRS: Record<AgentPlatform, string> = {\n 'claude-code': '.claude/skills',\n 'opencode': '.opencode/skills',\n 'cursor': '.cursor/skills',\n 'cline': '.cline/skills',\n 'windsurf': '.windsurf/skills',\n};\n\n/** Get the skills directory for a given platform */\nexport function getAgentSkillsDir(platform: AgentPlatform): string {\n return AGENT_SKILLS_DIRS[platform];\n}\n\n/** List all supported platforms */\nexport function getSupportedPlatforms(): AgentPlatform[] {\n return ['claude-code', 'opencode', 'cursor', 'cline', 'windsurf'];\n}\n","import { installSkill } from '../core/installer.js';\nimport { isGitUrl } from '../core/git-source.js';\nimport * as logger from '../utils/logger.js';\nimport type { SkillSource, AgentPlatform } from '../types/index.js';\n\nexport interface AddFlags {\n global: boolean;\n agent: string[];\n skill: string[];\n yes: boolean;\n list: boolean;\n all: boolean;\n fullDepth: boolean;\n copy: boolean;\n force: boolean;\n}\n\n/**\n * Parse POSIX-style flags for the add command.\n * Supports: -g/--global, -a/--agent, -s/--skill, -y/--yes,\n * -l/--list, --all, --full-depth, --copy, --force\n */\nexport function parseAddFlags(args: string[]): { source: string | null; flags: AddFlags } {\n const flags: AddFlags = {\n global: false,\n agent: [],\n skill: [],\n yes: false,\n list: false,\n all: false,\n fullDepth: false,\n copy: false,\n force: false,\n };\n\n let source: string | null = null;\n let i = 0;\n\n while (i < args.length) {\n const arg = args[i];\n\n // Long flags with = syntax (backward compat: --agent=claude-code)\n if (arg.startsWith('--') && arg.includes('=')) {\n const eqIdx = arg.indexOf('=');\n const key = arg.slice(2, eqIdx);\n const val = arg.slice(eqIdx + 1);\n switch (key) {\n case 'agent': flags.agent.push(val); break;\n case 'skill': flags.skill.push(val); break;\n default: break;\n }\n i++;\n continue;\n }\n\n switch (arg) {\n case '-g':\n case '--global':\n flags.global = true;\n i++;\n break;\n\n case '-a':\n case '--agent':\n // Consume following non-flag args as agent names\n i++;\n while (i < args.length && !args[i].startsWith('-')) {\n flags.agent.push(args[i]);\n i++;\n }\n break;\n\n case '-s':\n case '--skill':\n // Consume following non-flag args as skill names\n i++;\n while (i < args.length && !args[i].startsWith('-')) {\n flags.skill.push(args[i]);\n i++;\n }\n break;\n\n case '-y':\n case '--yes':\n flags.yes = true;\n i++;\n break;\n\n case '-l':\n case '--list':\n flags.list = true;\n i++;\n break;\n\n case '--all':\n flags.all = true;\n i++;\n break;\n\n case '--full-depth':\n flags.fullDepth = true;\n i++;\n break;\n\n case '--copy':\n flags.copy = true;\n i++;\n break;\n\n case '--force':\n flags.force = true;\n i++;\n break;\n\n default:\n // First non-flag argument is the source\n if (!arg.startsWith('-') && source === null) {\n source = arg;\n }\n i++;\n break;\n }\n }\n\n // --all implies --skill '*' --agent '*' -y\n if (flags.all) {\n if (flags.skill.length === 0) flags.skill.push('*');\n if (flags.agent.length === 0) flags.agent.push('*');\n flags.yes = true;\n }\n\n return { source, flags };\n}\n\n/** add command — install skills (compatible with `npx skills add`) */\nexport async function add(args: string[]): Promise<void> {\n if (args.length === 0) {\n logger.error('Usage: skill-master add <source> [options]');\n console.log('');\n console.log('Options:');\n console.log(' -g, --global Install globally (~/.agents/)');\n console.log(' -a, --agent <agents> Target agents (space-separated)');\n console.log(' -s, --skill <skills> Select skills (space-separated)');\n console.log(' -y, --yes Skip confirmations');\n console.log(' -l, --list List available skills without installing');\n console.log(' --all Install all skills to all agents');\n console.log(' --full-depth Search all subdirectories');\n console.log(' --copy Copy instead of symlink');\n console.log(' --force Force reinstall');\n process.exit(1);\n }\n\n const { source, flags } = parseAddFlags(args);\n\n if (!source) {\n logger.error('No source specified. Provide a GitHub URL, owner/repo, or local path.');\n process.exit(1);\n }\n\n const skillSource: SkillSource = isGitUrl(source)\n ? { type: 'git', url: source }\n : { type: 'local', path: source };\n\n const cwd = process.cwd();\n\n // If multiple agents specified, install for each\n const agents = flags.agent.length > 0 ? flags.agent : [undefined];\n\n try {\n for (const agent of agents) {\n await installSkill({\n source: skillSource,\n agent: agent as AgentPlatform | undefined,\n cwd,\n copy: flags.copy,\n force: flags.force,\n yes: flags.yes,\n });\n }\n } catch (err) {\n logger.error((err as Error).message);\n process.exit(1);\n }\n}\n","import { getRegistryEntry } from '../core/registry.js';\nimport { installSkill } from '../core/installer.js';\nimport { isGitUrl } from '../core/git-source.js';\nimport * as logger from '../utils/logger.js';\nimport { SkillNotFoundError } from '../utils/errors.js';\nimport type { SkillSource } from '../types/index.js';\n\nexport async function update(args: string[]): Promise<void> {\n if (args.length === 0) {\n logger.error('Usage: skill-master update <skill-name> [--force]');\n process.exit(1);\n }\n\n const skillName = args[0];\n const force = args.includes('--force');\n\n try {\n const entry = await getRegistryEntry(skillName);\n if (!entry) {\n throw new SkillNotFoundError(skillName);\n }\n\n logger.info(`Updating skill: ${skillName}`);\n logger.info(`Source: ${entry.source}`);\n\n const source: SkillSource = isGitUrl(entry.source)\n ? { type: 'git', url: entry.source }\n : { type: 'local', path: entry.source };\n\n await installSkill({\n source,\n agent: entry.agent,\n cwd: process.cwd(),\n force: true,\n });\n\n logger.success(`Skill \"${skillName}\" updated successfully!`);\n } catch (err) {\n logger.error((err as Error).message);\n process.exit(1);\n }\n}\n","import { getRegistryEntry, removeFromRegistry, listRegistry } from '../core/registry.js';\nimport { removePath } from '../utils/fs-helpers.js';\nimport { getSkillCanonicalPath, getSkillConfigPath } from '../utils/paths.js';\nimport * as logger from '../utils/logger.js';\nimport { SkillNotFoundError } from '../utils/errors.js';\n\nexport interface RemoveFlags {\n global: boolean;\n agent: string[];\n skill: string[];\n yes: boolean;\n all: boolean;\n purge: boolean;\n}\n\n/** Parse POSIX-style flags for the remove command */\nexport function parseRemoveFlags(args: string[]): { names: string[]; flags: RemoveFlags } {\n const flags: RemoveFlags = {\n global: false,\n agent: [],\n skill: [],\n yes: false,\n all: false,\n purge: false,\n };\n\n const names: string[] = [];\n let i = 0;\n\n while (i < args.length) {\n const arg = args[i];\n\n // Long flags with = syntax (backward compat: --agent=claude-code)\n if (arg.startsWith('--') && arg.includes('=')) {\n const eqIdx = arg.indexOf('=');\n const key = arg.slice(2, eqIdx);\n const val = arg.slice(eqIdx + 1);\n switch (key) {\n case 'agent': flags.agent.push(val); break;\n case 'skill': flags.skill.push(val); break;\n default: break;\n }\n i++;\n continue;\n }\n\n switch (arg) {\n case '-g':\n case '--global':\n flags.global = true;\n i++;\n break;\n\n case '-a':\n case '--agent':\n i++;\n while (i < args.length && !args[i].startsWith('-')) {\n flags.agent.push(args[i]);\n i++;\n }\n break;\n\n case '-s':\n case '--skill':\n i++;\n while (i < args.length && !args[i].startsWith('-')) {\n flags.skill.push(args[i]);\n i++;\n }\n break;\n\n case '-y':\n case '--yes':\n flags.yes = true;\n i++;\n break;\n\n case '--all':\n flags.all = true;\n i++;\n break;\n\n case '--purge':\n flags.purge = true;\n i++;\n break;\n\n default:\n // Non-flag arguments are skill names (positional)\n if (!arg.startsWith('-')) {\n names.push(arg);\n }\n i++;\n break;\n }\n }\n\n // --all implies removing all skills with -y\n if (flags.all) {\n flags.yes = true;\n }\n\n return { names, flags };\n}\n\n/** remove command — remove installed skills */\nexport async function remove(args: string[]): Promise<void> {\n if (args.length === 0) {\n logger.error('Usage: skill-master remove [skills...] [options]');\n console.log('');\n console.log('Options:');\n console.log(' -g, --global Remove from global (~/.agents/)');\n console.log(' -a, --agent <agents> Target agents (space-separated)');\n console.log(' -s, --skill <skills> Select skills (space-separated)');\n console.log(' -y, --yes Skip confirmations');\n console.log(' --all Remove all skills');\n console.log(' --purge Also remove config data');\n process.exit(1);\n }\n\n const { names, flags } = parseRemoveFlags(args);\n\n // Determine which skills to remove\n let skillNames: string[];\n if (flags.all) {\n const registry = await listRegistry();\n skillNames = Object.keys(registry);\n } else if (flags.skill.length > 0) {\n skillNames = flags.skill;\n } else {\n skillNames = names;\n }\n\n if (skillNames.length === 0) {\n logger.error('No skills specified. Provide skill names or use --all.');\n process.exit(1);\n }\n\n try {\n for (const skillName of skillNames) {\n const entry = await getRegistryEntry(skillName);\n if (!entry) {\n throw new SkillNotFoundError(skillName);\n }\n\n logger.info(`Removing skill: ${skillName}`);\n\n // Remove agent directory link/copy\n await removePath(entry.agent_path);\n logger.success(`Removed from ${entry.agent_path}`);\n\n // Remove canonical directory\n await removePath(entry.canonical_path);\n logger.success(`Removed from ${entry.canonical_path}`);\n\n // Optionally purge config\n if (flags.purge) {\n await removePath(getSkillConfigPath(skillName));\n logger.success('Purged config directory');\n }\n\n // Update registry\n await removeFromRegistry(skillName);\n logger.success(`Skill \"${skillName}\" removed successfully!`);\n }\n } catch (err) {\n logger.error((err as Error).message);\n process.exit(1);\n }\n}\n","import { listRegistry } from '../core/registry.js';\nimport { getEnvStatus, setEnvValue, getEnvEditPath } from '../core/env-manager.js';\nimport { getSkillCanonicalPath } from '../utils/paths.js';\nimport * as logger from '../utils/logger.js';\nimport { spawn } from 'node:child_process';\n\nexport async function env(args: string[]): Promise<void> {\n const subcommand = args[0];\n\n if (!subcommand || subcommand === 'list') {\n await envList();\n } else if (subcommand === 'set') {\n await envSet(args.slice(1));\n } else if (subcommand === 'edit') {\n await envEdit(args.slice(1));\n } else {\n logger.error('Usage: skill-master env <list|set|edit>');\n process.exit(1);\n }\n}\n\nasync function envList(): Promise<void> {\n const skills = await listRegistry();\n const entries = Object.entries(skills);\n\n if (entries.length === 0) {\n logger.info('No skills installed');\n return;\n }\n\n logger.blank();\n logger.tableHeader('Skill', 'Status', 'Keys');\n\n for (const [name, entry] of entries) {\n const status = await getEnvStatus(name, entry.env_keys);\n const statusIcon = status === 'configured' ? '✓' : status === 'partial' ? '⚠' : '✗';\n logger.tableRow(name, `${statusIcon} ${status}`, entry.env_keys.join(', '));\n }\n logger.blank();\n}\n\nasync function envSet(args: string[]): Promise<void> {\n if (args.length < 2) {\n logger.error('Usage: skill-master env set <skill> KEY=VALUE');\n process.exit(1);\n }\n\n const skillName = args[0];\n const [key, value] = args[1].split('=');\n\n if (!key || !value) {\n logger.error('Invalid format. Use: KEY=VALUE');\n process.exit(1);\n }\n\n try {\n const skillDir = getSkillCanonicalPath(skillName);\n await setEnvValue(skillName, key, value, skillDir);\n logger.success(`Set ${key} for ${skillName}`);\n } catch (err) {\n logger.error((err as Error).message);\n process.exit(1);\n }\n}\n\nasync function envEdit(args: string[]): Promise<void> {\n if (args.length === 0) {\n logger.error('Usage: skill-master env edit <skill>');\n process.exit(1);\n }\n\n const skillName = args[0];\n const envPath = getEnvEditPath(skillName);\n const editor = process.env.EDITOR || 'vi';\n\n logger.info(`Opening ${envPath} with ${editor}...`);\n\n const child = spawn(editor, [envPath], {\n stdio: 'inherit',\n shell: true,\n });\n\n child.on('exit', (code) => {\n if (code === 0) {\n logger.success('Saved');\n } else {\n logger.error('Editor exited with error');\n process.exit(1);\n }\n });\n}\n","import { listRegistry } from '../core/registry.js';\nimport * as logger from '../utils/logger.js';\n\nexport interface ListFlags {\n global: boolean;\n agent: string[];\n}\n\n/** Parse flags for the list command */\nexport function parseListFlags(args: string[]): ListFlags {\n const flags: ListFlags = {\n global: false,\n agent: [],\n };\n\n let i = 0;\n while (i < args.length) {\n const arg = args[i];\n\n if (arg.startsWith('--') && arg.includes('=')) {\n const eqIdx = arg.indexOf('=');\n const key = arg.slice(2, eqIdx);\n const val = arg.slice(eqIdx + 1);\n if (key === 'agent') flags.agent.push(val);\n i++;\n continue;\n }\n\n switch (arg) {\n case '-g':\n case '--global':\n flags.global = true;\n i++;\n break;\n case '-a':\n case '--agent':\n i++;\n while (i < args.length && !args[i].startsWith('-')) {\n flags.agent.push(args[i]);\n i++;\n }\n break;\n default:\n i++;\n break;\n }\n }\n\n return flags;\n}\n\n/** list command — list installed skills */\nexport async function list(args: string[] = []): Promise<void> {\n const flags = parseListFlags(args);\n const skills = await listRegistry();\n let entries = Object.entries(skills);\n\n // Filter by agent if specified\n if (flags.agent.length > 0) {\n entries = entries.filter(([, entry]) => flags.agent.includes(entry.agent));\n }\n\n if (entries.length === 0) {\n logger.info('No skills installed');\n return;\n }\n\n logger.blank();\n logger.tableHeader('Skill', 'Version', 'Platform', 'Installed');\n\n for (const [name, entry] of entries) {\n const date = new Date(entry.installed_at).toLocaleDateString();\n logger.tableRow(name, entry.version, entry.agent, date);\n }\n logger.blank();\n}\n","import { getRegistryEntry } from '../core/registry.js';\nimport { getEnvStatus } from '../core/env-manager.js';\nimport * as logger from '../utils/logger.js';\nimport { SkillNotFoundError } from '../utils/errors.js';\n\nexport async function info(args: string[]): Promise<void> {\n if (args.length === 0) {\n logger.error('Usage: skill-master info <skill-name>');\n process.exit(1);\n }\n\n const skillName = args[0];\n\n try {\n const entry = await getRegistryEntry(skillName);\n if (!entry) {\n throw new SkillNotFoundError(skillName);\n }\n\n const envStatus = await getEnvStatus(skillName, entry.env_keys);\n\n logger.blank();\n logger.info(`Skill: ${skillName}`);\n logger.kv('Version', entry.version);\n logger.kv('Platform', entry.agent);\n logger.kv('Source', entry.source);\n logger.kv('Installed', new Date(entry.installed_at).toLocaleString());\n logger.kv('Updated', new Date(entry.updated_at).toLocaleString());\n logger.kv('Canonical Path', entry.canonical_path);\n logger.kv('Agent Path', entry.agent_path);\n logger.kv('Capabilities', entry.capabilities.join(', '));\n logger.kv('Env Keys', entry.env_keys.join(', ') || 'none');\n logger.kv('Env Status', envStatus);\n logger.blank();\n } catch (err) {\n logger.error((err as Error).message);\n process.exit(1);\n }\n}\n","import { existsSync } from 'node:fs';\nimport { listRegistry } from '../core/registry.js';\nimport { getEnvStatus } from '../core/env-manager.js';\nimport { isSymlink } from '../utils/fs-helpers.js';\nimport { AGENTS_HOME, CONFIG_DIR, SKILLS_DIR, REGISTRY_PATH } from '../utils/paths.js';\nimport * as logger from '../utils/logger.js';\n\nexport async function doctor(): Promise<void> {\n logger.blank();\n logger.info('Running diagnostics...');\n logger.blank();\n\n let issues = 0;\n\n // Check directory structure\n logger.info('Checking directory structure...');\n const dirs = [AGENTS_HOME, CONFIG_DIR, SKILLS_DIR];\n for (const dir of dirs) {\n if (existsSync(dir)) {\n logger.success(`✓ ${dir}`);\n } else {\n logger.warn(`✗ ${dir} (missing)`);\n issues++;\n }\n }\n logger.blank();\n\n // Check registry\n logger.info('Checking registry...');\n if (existsSync(REGISTRY_PATH)) {\n logger.success(`✓ ${REGISTRY_PATH}`);\n try {\n const skills = await listRegistry();\n logger.info(` Found ${Object.keys(skills).length} skill(s)`);\n } catch (err) {\n logger.error(`✗ Registry corrupted: ${(err as Error).message}`);\n issues++;\n }\n } else {\n logger.info(` No registry found (will be created on first install)`);\n }\n logger.blank();\n\n // Check each skill\n logger.info('Checking installed skills...');\n try {\n const skills = await listRegistry();\n for (const [name, entry] of Object.entries(skills)) {\n logger.info(`Skill: ${name}`);\n\n // Check canonical path\n if (existsSync(entry.canonical_path)) {\n logger.success(` ✓ Canonical path exists`);\n } else {\n logger.error(` ✗ Canonical path missing: ${entry.canonical_path}`);\n issues++;\n }\n\n // Check agent path\n if (existsSync(entry.agent_path)) {\n const isLink = await isSymlink(entry.agent_path);\n logger.success(` ✓ Agent path exists (${isLink ? 'symlink' : 'copy'})`);\n } else {\n logger.error(` ✗ Agent path missing: ${entry.agent_path}`);\n issues++;\n }\n\n // Check env status\n const envStatus = await getEnvStatus(name, entry.env_keys);\n if (envStatus === 'configured') {\n logger.success(` ✓ Environment configured`);\n } else if (envStatus === 'partial') {\n logger.warn(` ⚠ Environment partially configured`);\n } else if (entry.env_keys.length > 0) {\n logger.warn(` ⚠ Environment not configured`);\n }\n }\n } catch (err) {\n logger.error(`Failed to check skills: ${(err as Error).message}`);\n issues++;\n }\n\n logger.blank();\n if (issues === 0) {\n logger.success('All checks passed!');\n } else {\n logger.warn(`Found ${issues} issue(s)`);\n }\n logger.blank();\n}\n","import * as logger from '../utils/logger.js';\n\n/** find command — search for skills from the registry */\nexport async function find(args: string[]): Promise<void> {\n const query = args.filter(a => !a.startsWith('-')).join(' ').trim();\n\n if (!query) {\n console.log('Usage: skill-master find <query>');\n console.log('');\n console.log('Search for skills in the online registry.');\n console.log('');\n console.log('Examples:');\n console.log(' skill-master find git');\n console.log(' skill-master find \"code review\"');\n process.exit(0);\n }\n\n logger.info(`Searching for \"${query}\"...`);\n\n try {\n const url = `https://skills.sh/api/search?q=${encodeURIComponent(query)}`;\n const response = await fetch(url, {\n headers: { 'Accept': 'application/json' },\n signal: AbortSignal.timeout(10_000),\n });\n\n if (!response.ok) {\n logger.error(`Search API returned ${response.status}: ${response.statusText}`);\n process.exit(1);\n }\n\n const data = await response.json() as SearchResult[];\n\n if (!Array.isArray(data) || data.length === 0) {\n logger.info('No skills found matching your query.');\n return;\n }\n\n logger.blank();\n logger.tableHeader('Name', 'Source', 'Installs');\n\n for (const item of data) {\n logger.tableRow(\n item.name ?? '—',\n item.source ?? '—',\n String(item.installs ?? 0),\n );\n }\n logger.blank();\n } catch (err) {\n if ((err as Error).name === 'TimeoutError') {\n logger.error('Search request timed out. Please try again.');\n } else {\n logger.error(`Search failed: ${(err as Error).message}`);\n }\n process.exit(1);\n }\n}\n\ninterface SearchResult {\n name?: string;\n source?: string;\n installs?: number;\n}\n","import { existsSync } from 'node:fs';\nimport { join, basename } from 'node:path';\nimport { ensureDir, writeText } from '../utils/fs-helpers.js';\nimport * as logger from '../utils/logger.js';\n\nconst SKILL_MD_TEMPLATE = `---\nname: {{NAME}}\nversion: 0.1.0\nauthor: \"\"\ndescription: \"\"\nallowed-tools:\n - Read\n - Edit\n - Write\n - Bash\n - Glob\n - Grep\nuser-invocable: true\n---\n\n# {{NAME}}\n\n<!-- Describe what this skill does -->\n`;\n\n/** init command — create a new skill template */\nexport async function init(args: string[]): Promise<void> {\n const nameArg = args.filter(a => !a.startsWith('-'))[0];\n const cwd = process.cwd();\n\n let targetDir: string;\n let skillName: string;\n\n if (nameArg) {\n targetDir = join(cwd, nameArg);\n skillName = nameArg;\n } else {\n targetDir = cwd;\n skillName = basename(cwd);\n }\n\n const skillMdPath = join(targetDir, 'SKILL.md');\n\n if (existsSync(skillMdPath)) {\n logger.error(`SKILL.md already exists at ${skillMdPath}`);\n process.exit(1);\n }\n\n await ensureDir(targetDir);\n\n const content = SKILL_MD_TEMPLATE\n .replace(/\\{\\{NAME\\}\\}/g, skillName);\n\n await writeText(skillMdPath, content);\n logger.success(`Created ${skillMdPath}`);\n logger.info(`Edit the file to configure your skill.`);\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { listRegistry } from '../core/registry.js';\nimport { isGitUrl, parseGitUrl } from '../core/git-source.js';\nimport * as logger from '../utils/logger.js';\n\nconst execFileAsync = promisify(execFile);\n\n/** check command — check for skill updates */\nexport async function check(_args: string[]): Promise<void> {\n const skills = await listRegistry();\n const entries = Object.entries(skills);\n\n if (entries.length === 0) {\n logger.info('No skills installed');\n return;\n }\n\n logger.info('Checking for updates...');\n logger.blank();\n\n let updatable = 0;\n\n for (const [name, entry] of entries) {\n if (!isGitUrl(entry.source)) {\n logger.info(`${name}: local source — skipped`);\n continue;\n }\n\n try {\n const remoteHead = await getRemoteHead(entry.source);\n if (!remoteHead) {\n logger.warn(`${name}: unable to query remote`);\n continue;\n }\n\n // Compare with installed version (stored as git short hash or semver)\n // If version differs from remote HEAD, an update is available\n const isUpToDate = entry.version === remoteHead.slice(0, entry.version.length);\n if (isUpToDate) {\n logger.success(`${name}: up to date (${entry.version})`);\n } else {\n logger.warn(`${name}: update available (${entry.version} → ${remoteHead.slice(0, 7)})`);\n updatable++;\n }\n } catch {\n logger.warn(`${name}: failed to check remote`);\n }\n }\n\n logger.blank();\n if (updatable === 0) {\n logger.success('All skills are up to date!');\n } else {\n logger.info(`${updatable} skill(s) can be updated. Run \"skill-master update <name>\" to update.`);\n }\n}\n\n/** Get the latest commit hash from a remote git repo */\nasync function getRemoteHead(source: string): Promise<string | null> {\n try {\n const { owner, repo } = parseGitUrl(source);\n const url = `https://github.com/${owner}/${repo}.git`;\n const { stdout } = await execFileAsync('git', ['ls-remote', url, 'HEAD'], {\n timeout: 15_000,\n });\n const match = stdout.trim().split(/\\s+/)[0];\n return match || null;\n } catch {\n return null;\n }\n}\n","#!/usr/bin/env node\n\nimport { add } from './commands/add.js';\nimport { update } from './commands/update.js';\nimport { remove } from './commands/remove.js';\nimport { env } from './commands/env.js';\nimport { list } from './commands/list.js';\nimport { info } from './commands/info.js';\nimport { doctor } from './commands/doctor.js';\nimport { find } from './commands/find.js';\nimport { init } from './commands/init.js';\nimport { check } from './commands/check.js';\nimport * as logger from './utils/logger.js';\n\nconst VERSION = '0.1.0';\n\nconst HELP = `\nskill-master v${VERSION}\n\nUsage:\n skill-master add <source> [options] Install skills (aliases: install, a, i)\n skill-master remove [skills...] [opts] Remove skills (aliases: rm, r)\n skill-master list [options] List installed skills (alias: ls)\n skill-master find [query] Search for skills (aliases: search, f, s)\n skill-master update [skill] Update skills (alias: upgrade)\n skill-master init [name] Create a new skill template\n skill-master check Check for skill updates\n skill-master env <list|set|edit> Manage environment variables\n skill-master info <skill-name> Show skill details\n skill-master doctor Run diagnostics\n\nAdd Options:\n -g, --global Install globally (~/.agents/)\n -a, --agent <agents> Target agents (space-separated)\n -s, --skill <skills> Select skills (space-separated)\n -y, --yes Skip confirmations\n -l, --list List available skills without installing\n --all Install all skills to all agents\n --full-depth Search all subdirectories\n --copy Copy instead of symlink\n --force Force reinstall\n\nExamples:\n skill-master add owner/repo\n skill-master add https://github.com/user/skill -a claude-code cursor -y\n skill-master add ./local-skill --agent=cursor --copy\n skill-master remove my-skill --purge\n skill-master find \"code review\"\n skill-master init my-new-skill\n skill-master check\n`;\n\nasync function main() {\n const args = process.argv.slice(2);\n\n if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {\n console.log(HELP);\n process.exit(0);\n }\n\n if (args[0] === '--version' || args[0] === '-v') {\n console.log(VERSION);\n process.exit(0);\n }\n\n const command = args[0];\n const commandArgs = args.slice(1);\n\n try {\n switch (command) {\n // add (primary) with aliases: install, a, i\n case 'add':\n case 'a':\n case 'install':\n case 'i':\n await add(commandArgs);\n break;\n\n // remove with aliases: rm, r\n case 'remove':\n case 'rm':\n case 'r':\n await remove(commandArgs);\n break;\n\n // list with alias: ls\n case 'list':\n case 'ls':\n await list(commandArgs);\n break;\n\n // find with aliases: search, f, s\n case 'find':\n case 'search':\n case 'f':\n case 's':\n await find(commandArgs);\n break;\n\n // update with alias: upgrade\n case 'update':\n case 'upgrade':\n await update(commandArgs);\n break;\n\n // init\n case 'init':\n await init(commandArgs);\n break;\n\n // check\n case 'check':\n await check(commandArgs);\n break;\n\n // env, info, doctor — skill-master extensions\n case 'env':\n await env(commandArgs);\n break;\n case 'info':\n await info(commandArgs);\n break;\n case 'doctor':\n await doctor();\n break;\n\n default:\n logger.error(`Unknown command: ${command}`);\n console.log(HELP);\n process.exit(1);\n }\n } catch (err) {\n logger.error((err as Error).message);\n if (process.env.DEBUG) {\n console.error(err);\n }\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":["join","existsSync","existsSync","join","existsSync","existsSync","join","join","join","join","existsSync","existsSync","existsSync","join","homedir","existsSync","join","info","existsSync","existsSync","existsSync","join","join","existsSync","execFile","promisify","execFileAsync","promisify","execFile","info"]}
1
+ {"version":3,"sources":["../src/core/installer.ts","../src/core/git-source.ts","../src/utils/fs-helpers.ts","../src/utils/errors.ts","../src/utils/logger.ts","../src/core/skill-parser.ts","../src/core/env-manager.ts","../src/utils/paths.ts","../src/platform/agents.ts","../src/core/registry.ts","../src/commands/add.ts","../src/commands/update.ts","../src/commands/remove.ts","../src/commands/env.ts","../src/commands/list.ts","../src/commands/info.ts","../src/commands/doctor.ts","../src/commands/find.ts","../src/commands/init.ts","../src/commands/check.ts","../src/cli.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { cloneRepo, isGitUrl, isLocalPath } from './git-source.js';\nimport { findSkillDirectory, readSkillMd, inferCapabilities, extractEnvKeys } from './skill-parser.js';\nimport { backupEnv, restoreEnv } from './env-manager.js';\nimport { updateRegistry } from './registry.js';\nimport { detectPlatform, getAgentSkillsDir } from '../platform/detector.js';\nimport { copyDir, removePath, symlinkOrCopy, ensureDir, readTextSafe } from '../utils/fs-helpers.js';\nimport { getSkillCanonicalPath, getAgentSkillPath } from '../utils/paths.js';\nimport * as logger from '../utils/logger.js';\nimport { SkillNotFoundError, SkillParseError } from '../utils/errors.js';\nimport type { InstallOptions, RegistryEntry } from '../types/index.js';\n\nconst TOTAL_STEPS = 9;\n\n/**\n * Main installation engine — 9-step process:\n * 1. fetchSource → clone/copy to temp\n * 2. findSkillDir → locate SKILL.md\n * 3. parseSkillMd → parse frontmatter\n * 4. detectAgent → determine target platform\n * 5. backupEnv → preserve existing .env\n * 6. cleanAndInstall → rm old → copy new to canonical\n * 7. restoreEnv → restore .env to both locations\n * 8. linkOrCopy → symlink/copy to agent dir\n * 9. updateRegistry → update registry.json\n */\nexport async function installSkill(options: InstallOptions): Promise<void> {\n const { source, cwd, copy = false, force = false } = options;\n\n // Step 1: Fetch source\n logger.step(1, TOTAL_STEPS, 'Fetching skill source...');\n let sourceDir: string;\n\n if (source.type === 'git') {\n sourceDir = await cloneRepo(source.url!, source.branch);\n } else if (source.type === 'local') {\n sourceDir = source.path!;\n if (!existsSync(sourceDir)) {\n throw new SkillNotFoundError(sourceDir);\n }\n } else {\n throw new SkillParseError('Invalid source type');\n }\n\n // Step 2: Find skill directory\n logger.step(2, TOTAL_STEPS, 'Locating SKILL.md...');\n const skillDir = await findSkillDirectory(sourceDir);\n if (!skillDir) {\n throw new SkillNotFoundError(`No SKILL.md found in ${sourceDir}`);\n }\n\n // Step 3: Parse SKILL.md\n logger.step(3, TOTAL_STEPS, 'Parsing SKILL.md...');\n const parsed = await readSkillMd(skillDir);\n if (!parsed) {\n throw new SkillParseError('Failed to read SKILL.md');\n }\n const skillName = parsed.frontmatter.name;\n logger.info(`Found skill: ${skillName} v${parsed.frontmatter.version}`);\n\n // Step 4: Detect agent platform\n logger.step(4, TOTAL_STEPS, 'Detecting agent platform...');\n const agent = options.agent ?? detectPlatform(cwd);\n logger.info(`Target platform: ${agent}`);\n\n // Step 5: Backup existing .env\n logger.step(5, TOTAL_STEPS, 'Backing up .env...');\n const agentSkillDir = getAgentSkillPath(cwd, agent, skillName);\n const envBackup = await backupEnv(skillName, agentSkillDir);\n if (envBackup) {\n logger.success(`Backed up ${Object.keys(envBackup).length} env key(s)`);\n } else {\n logger.info('No existing .env found');\n }\n\n // Step 6: Clean and install to canonical path\n logger.step(6, TOTAL_STEPS, 'Installing to canonical path...');\n const canonicalPath = getSkillCanonicalPath(skillName);\n\n if (existsSync(canonicalPath) && !force) {\n logger.info('Replacing existing installation');\n }\n await removePath(canonicalPath);\n await copyDir(skillDir, canonicalPath);\n logger.success(`Installed to ${canonicalPath}`);\n\n // Step 7: Restore .env\n logger.step(7, TOTAL_STEPS, 'Restoring .env...');\n if (envBackup) {\n await restoreEnv(skillName, envBackup, canonicalPath);\n logger.success('.env restored successfully');\n } else {\n // Check if there's a .env.example to hint about\n const examplePath = join(canonicalPath, '.env.example');\n if (existsSync(examplePath)) {\n logger.warn('Found .env.example — run `skill-master env edit ' + skillName + '` to configure');\n }\n }\n\n // Step 8: Link or copy to agent directory\n logger.step(8, TOTAL_STEPS, `Linking to ${agent} skills directory...`);\n const agentPath = getAgentSkillPath(cwd, agent, skillName);\n const linkType = await symlinkOrCopy(canonicalPath, agentPath, copy);\n logger.success(`${linkType === 'symlink' ? 'Symlinked' : 'Copied'} to ${agentPath}`);\n\n // Step 9: Update registry\n logger.step(9, TOTAL_STEPS, 'Updating registry...');\n const capabilities = parsed.frontmatter.capabilities ?? inferCapabilities(parsed.frontmatter['allowed-tools']);\n\n // Extract env keys from .env.example\n const envExampleContent = await readTextSafe(join(canonicalPath, '.env.example'));\n const envKeys = envExampleContent ? extractEnvKeys(envExampleContent) : [];\n\n const now = new Date().toISOString();\n const entry: RegistryEntry = {\n source: source.type === 'git' ? source.url! : source.path!,\n version: parsed.frontmatter.version,\n installed_at: now,\n updated_at: now,\n agent,\n env_keys: envKeys,\n capabilities,\n canonical_path: canonicalPath,\n agent_path: agentPath,\n };\n\n await updateRegistry(skillName, entry);\n logger.blank();\n logger.success(`Skill \"${skillName}\" installed successfully!`);\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { existsSync } from 'node:fs';\nimport { ensureDir, createTempDir } from '../utils/fs-helpers.js';\nimport { GitCloneError } from '../utils/errors.js';\nimport * as logger from '../utils/logger.js';\n\nconst execFileAsync = promisify(execFile);\n\n/** Check if a string looks like a git URL or GitHub shorthand (owner/repo) */\nexport function isGitUrl(source: string): boolean {\n return (\n source.startsWith('https://') ||\n source.startsWith('http://') ||\n source.startsWith('git@') ||\n source.startsWith('git://') ||\n source.includes('github.com/') ||\n source.includes('gitlab.com/') ||\n /^[a-zA-Z0-9_.-]+\\/[a-zA-Z0-9_.-]+$/.test(source)\n );\n}\n\n/** Normalize a GitHub shorthand or URL to a full clone URL */\nexport function normalizeGitUrl(source: string): string {\n // Already a full URL\n if (source.startsWith('https://') || source.startsWith('http://') ||\n source.startsWith('git@') || source.startsWith('git://')) {\n // Ensure .git suffix for HTTPS URLs\n if (source.startsWith('https://') && !source.endsWith('.git')) {\n return source + '.git';\n }\n return source;\n }\n\n // GitHub shorthand: owner/repo\n if (/^[a-zA-Z0-9_.-]+\\/[a-zA-Z0-9_.-]+$/.test(source)) {\n return `https://github.com/${source}.git`;\n }\n\n return source;\n}\n\n/** Parse a GitHub URL into owner and repo */\nexport function parseGitUrl(url: string): { owner: string; repo: string; branch?: string } {\n // Handle tree/branch in URL: github.com/owner/repo/tree/branch\n const treeMatch = url.match(/github\\.com\\/([^/]+)\\/([^/]+)\\/tree\\/(.+)/);\n if (treeMatch) {\n return {\n owner: treeMatch[1],\n repo: treeMatch[2].replace(/\\.git$/, ''),\n branch: treeMatch[3],\n };\n }\n\n // Standard URL: github.com/owner/repo\n const match = url.match(/github\\.com[/:]([^/]+)\\/([^/.]+)/);\n if (match) {\n return { owner: match[1], repo: match[2] };\n }\n\n throw new GitCloneError(url, 'Unable to parse GitHub URL');\n}\n\n/** Clone a git repository to a temporary directory */\nexport async function cloneRepo(\n url: string,\n branch?: string,\n): Promise<string> {\n const normalizedUrl = normalizeGitUrl(url);\n const tempDir = createTempDir();\n await ensureDir(tempDir);\n\n const args = ['clone', '--depth', '1'];\n if (branch) {\n args.push('--branch', branch);\n }\n args.push(normalizedUrl, tempDir);\n\n logger.debug(`Cloning ${normalizedUrl} to ${tempDir}`);\n\n try {\n await execFileAsync('git', args, { timeout: 60_000 });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new GitCloneError(url, msg);\n }\n\n return tempDir;\n}\n\n/** Check if a local path exists and contains a skill */\nexport function isLocalPath(source: string): boolean {\n return existsSync(source);\n}","import { mkdir, cp, readFile, writeFile, rename, symlink, lstat, rm } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { tmpdir } from 'node:os';\nimport { randomBytes } from 'node:crypto';\n\n/** Ensure a directory exists (recursive) */\nexport async function ensureDir(dir: string): Promise<void> {\n await mkdir(dir, { recursive: true });\n}\n\n/** Recursively copy a directory */\nexport async function copyDir(src: string, dest: string): Promise<void> {\n await ensureDir(dest);\n await cp(src, dest, { recursive: true, force: true });\n}\n\n/** Remove a directory or file recursively */\nexport async function removePath(target: string): Promise<void> {\n if (existsSync(target)) {\n await rm(target, { recursive: true, force: true });\n }\n}\n\n/** Atomic JSON write: write to .tmp then rename */\nexport async function atomicWriteJson(filePath: string, data: unknown): Promise<void> {\n await ensureDir(dirname(filePath));\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, JSON.stringify(data, null, 2) + '\\n', 'utf-8');\n await rename(tmpPath, filePath);\n}\n\n/** Safely read and parse a JSON file, return null on failure */\nexport async function readJsonSafe<T>(filePath: string): Promise<T | null> {\n try {\n const content = await readFile(filePath, 'utf-8');\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\n/** Read a text file, return null if not found */\nexport async function readTextSafe(filePath: string): Promise<string | null> {\n try {\n return await readFile(filePath, 'utf-8');\n } catch {\n return null;\n }\n}\n\n/** Write text to a file, ensuring parent directory exists */\nexport async function writeText(filePath: string, content: string): Promise<void> {\n await ensureDir(dirname(filePath));\n await writeFile(filePath, content, 'utf-8');\n}\n\n/** Create a symlink, or copy if symlink fails (Windows fallback) */\nexport async function symlinkOrCopy(target: string, linkPath: string, forceCopy = false): Promise<'symlink' | 'copy'> {\n await ensureDir(dirname(linkPath));\n\n // Remove existing link/dir\n await removePath(linkPath);\n\n if (forceCopy) {\n await copyDir(target, linkPath);\n return 'copy';\n }\n\n try {\n await symlink(target, linkPath, 'dir');\n return 'symlink';\n } catch {\n // Fallback to copy on platforms that don't support symlinks\n await copyDir(target, linkPath);\n return 'copy';\n }\n}\n\n/** Check if a path is a symlink */\nexport async function isSymlink(path: string): Promise<boolean> {\n try {\n const stat = await lstat(path);\n return stat.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/** Create a temporary directory with a unique name */\nexport function createTempDir(): string {\n const id = randomBytes(8).toString('hex');\n return join(tmpdir(), `skill-master-${id}`);\n}\n","/** Base error class for skill-master */\nexport class SkillManagerError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SkillManagerError';\n }\n}\n\n/** Skill not found in registry or filesystem */\nexport class SkillNotFoundError extends SkillManagerError {\n constructor(skillName: string) {\n super(`Skill \"${skillName}\" not found`);\n this.name = 'SkillNotFoundError';\n }\n}\n\n/** Required .env key is missing */\nexport class EnvMissingError extends SkillManagerError {\n constructor(skillName: string, keys: string[]) {\n super(`Skill \"${skillName}\" is missing env keys: ${keys.join(', ')}`);\n this.name = 'EnvMissingError';\n }\n}\n\n/** Registry file is corrupted or invalid */\nexport class RegistryCorruptError extends SkillManagerError {\n constructor(detail?: string) {\n super(`Registry is corrupted${detail ? ': ' + detail : ''}`);\n this.name = 'RegistryCorruptError';\n }\n}\n\n/** Git clone operation failed */\nexport class GitCloneError extends SkillManagerError {\n constructor(url: string, detail?: string) {\n super(`Failed to clone \"${url}\"${detail ? ': ' + detail : ''}`);\n this.name = 'GitCloneError';\n }\n}\n\n/** SKILL.md parsing or validation failed */\nexport class SkillParseError extends SkillManagerError {\n constructor(detail: string) {\n super(`Failed to parse SKILL.md: ${detail}`);\n this.name = 'SkillParseError';\n }\n}\n\n/** Platform detection failed or unsupported */\nexport class PlatformError extends SkillManagerError {\n constructor(detail: string) {\n super(`Platform error: ${detail}`);\n this.name = 'PlatformError';\n }\n}\n","import chalk from 'chalk';\n\nconst PREFIX = chalk.blue('skill-master');\n\n/** Informational message */\nexport function info(msg: string): void {\n console.log(`${PREFIX} ${chalk.cyan('info')} ${msg}`);\n}\n\n/** Success message */\nexport function success(msg: string): void {\n console.log(`${PREFIX} ${chalk.green('✔')} ${msg}`);\n}\n\n/** Warning message */\nexport function warn(msg: string): void {\n console.log(`${PREFIX} ${chalk.yellow('⚠')} ${msg}`);\n}\n\n/** Error message */\nexport function error(msg: string): void {\n console.error(`${PREFIX} ${chalk.red('✖')} ${msg}`);\n}\n\n/** Debug message (only when DEBUG env is set) */\nexport function debug(msg: string): void {\n if (process.env.DEBUG) {\n console.log(`${PREFIX} ${chalk.gray('debug')} ${msg}`);\n }\n}\n\n/** Step indicator with number */\nexport function step(num: number, total: number, msg: string): void {\n const counter = chalk.gray(`[${num}/${total}]`);\n console.log(`${PREFIX} ${counter} ${msg}`);\n}\n\n/** Print a blank line */\nexport function blank(): void {\n console.log();\n}\n\n/** Print a key-value pair */\nexport function kv(key: string, value: string): void {\n console.log(` ${chalk.gray(key + ':')} ${value}`);\n}\n\n/** Print a table header */\nexport function tableHeader(...cols: string[]): void {\n console.log(chalk.bold(cols.map(c => c.padEnd(20)).join('')));\n console.log(chalk.gray('─'.repeat(cols.length * 20)));\n}\n\n/** Print a table row */\nexport function tableRow(...cols: string[]): void {\n console.log(cols.map(c => c.padEnd(20)).join(''));\n}\n","import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport { readdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { readTextSafe } from '../utils/fs-helpers.js';\nimport { SkillParseError } from '../utils/errors.js';\nimport type { ParsedSkill, SkillFrontmatter, Capability } from '../types/index.js';\n\n/** Tool-to-capability reverse mapping for Claude Code tools */\nconst TOOL_CAPABILITY_MAP: Record<string, Capability> = {\n 'Bash': 'shell',\n 'Read': 'read_file',\n 'Write': 'write_file',\n 'Edit': 'edit_file',\n 'Glob': 'find_file',\n 'Grep': 'search_content',\n 'Task': 'sub_task',\n 'WebFetch': 'web_fetch',\n 'WebSearch': 'web_search',\n};\n\n/** Parse a SKILL.md file content into frontmatter + body */\nexport function parseSkillMd(content: string): ParsedSkill {\n const match = content.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n if (!match) {\n throw new SkillParseError('No valid frontmatter block found');\n }\n\n const rawFrontmatter = match[1];\n const body = match[2];\n\n let frontmatter: SkillFrontmatter;\n try {\n frontmatter = parseYaml(rawFrontmatter) as SkillFrontmatter;\n } catch (err) {\n throw new SkillParseError(`YAML parse error: ${(err as Error).message}`);\n }\n\n validateFrontmatter(frontmatter);\n\n return { frontmatter, body, rawFrontmatter };\n}\n\n/** Validate required frontmatter fields */\nexport function validateFrontmatter(fm: SkillFrontmatter): void {\n if (!fm.name || typeof fm.name !== 'string') {\n throw new SkillParseError('Missing or invalid \"name\" field');\n }\n if (!fm.version || typeof fm.version !== 'string') {\n throw new SkillParseError('Missing or invalid \"version\" field');\n }\n if (!Array.isArray(fm['allowed-tools']) || fm['allowed-tools'].length === 0) {\n throw new SkillParseError('Missing or empty \"allowed-tools\" field');\n }\n}\n\n/** Infer abstract capabilities from allowed-tools list */\nexport function inferCapabilities(allowedTools: string[]): Capability[] {\n const caps = new Set<Capability>();\n for (const tool of allowedTools) {\n const cap = TOOL_CAPABILITY_MAP[tool];\n if (cap) {\n caps.add(cap);\n }\n }\n return [...caps];\n}\n\n/** Serialize a ParsedSkill back to SKILL.md format */\nexport function serializeSkillMd(parsed: ParsedSkill): string {\n const yamlStr = stringifyYaml(parsed.frontmatter, { lineWidth: 0 }).trimEnd();\n return `---\\n${yamlStr}\\n---\\n${parsed.body}`;\n}\n\n/** Search for SKILL.md files within a directory (looks in .claude/skills/*) */\nexport async function findSkillDirectory(dir: string): Promise<string | null> {\n // Direct SKILL.md in root\n if (existsSync(join(dir, 'SKILL.md'))) {\n return dir;\n }\n\n // Search in .claude/skills/*/SKILL.md\n const skillsRoot = join(dir, '.claude', 'skills');\n if (!existsSync(skillsRoot)) {\n return null;\n }\n\n try {\n const entries = await readdir(skillsRoot, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const skillMdPath = join(skillsRoot, entry.name, 'SKILL.md');\n if (existsSync(skillMdPath)) {\n return join(skillsRoot, entry.name);\n }\n }\n }\n } catch {\n return null;\n }\n\n return null;\n}\n\n/** Read and parse a SKILL.md from a directory */\nexport async function readSkillMd(dir: string): Promise<ParsedSkill | null> {\n const content = await readTextSafe(join(dir, 'SKILL.md'));\n if (!content) return null;\n return parseSkillMd(content);\n}\n\n/** Extract env keys from a .env.example file */\nexport function extractEnvKeys(envExampleContent: string): string[] {\n const keys: string[] = [];\n for (const line of envExampleContent.split('\\n')) {\n const trimmed = line.trim();\n if (trimmed && !trimmed.startsWith('#')) {\n const match = trimmed.match(/^([A-Z_][A-Z0-9_]*)=/);\n if (match) {\n keys.push(match[1]);\n }\n }\n }\n return keys;\n}\n","import { join } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { readTextSafe, writeText, ensureDir } from '../utils/fs-helpers.js';\nimport { getSkillConfigPath, getSkillCanonicalPath } from '../utils/paths.js';\nimport * as logger from '../utils/logger.js';\nimport type { EnvStatus } from '../types/index.js';\n\n/** Parse a .env file content into key-value pairs */\nexport function parseEnvFile(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex === -1) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n // Strip surrounding quotes\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1);\n }\n result[key] = value;\n }\n return result;\n}\n\n/** Serialize key-value pairs back to .env format */\nexport function serializeEnv(data: Record<string, string>): string {\n return Object.entries(data)\n .map(([key, value]) => `${key}=${value}`)\n .join('\\n') + '\\n';\n}\n\n/**\n * Backup .env for a skill, searching multiple locations by priority:\n * 1. ~/.agents/config/<skill>/.env (persistent)\n * 2. agentSkillDir/.env (current agent dir, e.g. .claude/skills/<skill>)\n * 3. ~/.agents/skills/<skill>/.env (canonical)\n */\nexport async function backupEnv(\n skillName: string,\n agentSkillDir?: string,\n): Promise<Record<string, string> | null> {\n const locations = [\n join(getSkillConfigPath(skillName), '.env'),\n ...(agentSkillDir ? [join(agentSkillDir, '.env')] : []),\n join(getSkillCanonicalPath(skillName), '.env'),\n ];\n\n for (const loc of locations) {\n const content = await readTextSafe(loc);\n if (content) {\n const data = parseEnvFile(content);\n if (Object.keys(data).length > 0) {\n logger.debug(`Backed up .env from ${loc}`);\n return data;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Restore .env to both persistent and skill directory locations.\n * Merges with .env.example if present.\n */\nexport async function restoreEnv(\n skillName: string,\n envData: Record<string, string>,\n skillDir: string,\n): Promise<void> {\n // Read .env.example from skill dir if exists\n const exampleContent = await readTextSafe(join(skillDir, '.env.example'));\n let finalContent: string;\n\n if (exampleContent) {\n finalContent = mergeEnv(envData, exampleContent);\n } else {\n finalContent = serializeEnv(envData);\n }\n\n // Write to persistent config location\n const configEnvPath = join(getSkillConfigPath(skillName), '.env');\n await writeText(configEnvPath, finalContent);\n\n // Write to skill directory (for compatibility with loadApiKey)\n const skillEnvPath = join(skillDir, '.env');\n await writeText(skillEnvPath, finalContent);\n\n logger.debug(`Restored .env to ${configEnvPath} and ${skillEnvPath}`);\n}\n\n/**\n * Merge existing env data with .env.example template.\n * - Existing keys are NEVER overwritten\n * - New keys from example are appended with empty values and comments\n */\nexport function mergeEnv(\n existing: Record<string, string>,\n exampleContent: string,\n): string {\n const lines: string[] = [];\n const usedKeys = new Set<string>();\n\n // First, write all existing keys\n for (const [key, value] of Object.entries(existing)) {\n lines.push(`${key}=${value}`);\n usedKeys.add(key);\n }\n\n // Then, append new keys from example\n const exampleKeys = parseEnvFile(exampleContent);\n const newKeys = Object.keys(exampleKeys).filter(k => !usedKeys.has(k));\n\n if (newKeys.length > 0) {\n lines.push('');\n lines.push('# New keys added by skill update (please configure):');\n for (const key of newKeys) {\n lines.push(`# ${key}=`);\n }\n }\n\n return lines.join('\\n') + '\\n';\n}\n\n/** Check the .env configuration status for a skill */\nexport async function getEnvStatus(\n skillName: string,\n requiredKeys: string[],\n): Promise<EnvStatus> {\n if (requiredKeys.length === 0) return 'configured';\n\n const configEnvPath = join(getSkillConfigPath(skillName), '.env');\n const content = await readTextSafe(configEnvPath);\n\n if (!content) return 'missing';\n\n const data = parseEnvFile(content);\n const configuredKeys = Object.entries(data)\n .filter(([, v]) => v && !v.includes('your_') && !v.includes('_here'))\n .map(([k]) => k);\n\n const allConfigured = requiredKeys.every(k => configuredKeys.includes(k));\n const someConfigured = requiredKeys.some(k => configuredKeys.includes(k));\n\n if (allConfigured) return 'configured';\n if (someConfigured) return 'partial';\n return 'missing';\n}\n\n/** Set a single env value for a skill */\nexport async function setEnvValue(\n skillName: string,\n key: string,\n value: string,\n skillDir?: string,\n): Promise<void> {\n const configEnvPath = join(getSkillConfigPath(skillName), '.env');\n const content = await readTextSafe(configEnvPath);\n const data = content ? parseEnvFile(content) : {};\n\n data[key] = value;\n const newContent = serializeEnv(data);\n\n // Write to persistent location\n await writeText(configEnvPath, newContent);\n\n // Sync to skill directory if provided\n if (skillDir) {\n await writeText(join(skillDir, '.env'), newContent);\n }\n}\n\n/** Get the .env file path for editing */\nexport function getEnvEditPath(skillName: string): string {\n return join(getSkillConfigPath(skillName), '.env');\n}\n","import { homedir } from 'node:os';\nimport { join } from 'node:path';\n\n/** Root directory for all skill-master data */\nexport const AGENTS_HOME = join(homedir(), '.agents');\n\n/** Persistent user config (API keys etc.) */\nexport const CONFIG_DIR = join(AGENTS_HOME, 'config');\n\n/** Canonical skill code storage */\nexport const SKILLS_DIR = join(AGENTS_HOME, 'skills');\n\n/** Registry file path */\nexport const REGISTRY_PATH = join(AGENTS_HOME, 'registry.json');\n\n/** Get canonical path for a skill's code */\nexport function getSkillCanonicalPath(name: string): string {\n return join(SKILLS_DIR, name);\n}\n\n/** Get persistent config path for a skill (holds .env) */\nexport function getSkillConfigPath(name: string): string {\n return join(CONFIG_DIR, name);\n}\n\n// Re-export from agents.ts — eliminates duplicate AGENT_SKILL_DIRS mapping\nexport { getAgentSkillPath, getAgentSkillsRoot } from '../platform/agents.js';\n","import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\n\nconst home = homedir();\nconst configHome = process.env.XDG_CONFIG_HOME?.trim() || join(home, '.config');\nconst codexHome = process.env.CODEX_HOME?.trim() || join(home, '.codex');\nconst claudeHome = process.env.CLAUDE_CONFIG_DIR?.trim() || join(home, '.claude');\n\nexport interface AgentConfig {\n name: string;\n displayName: string;\n skillsDir: string;\n globalSkillsDir: string;\n detectMarker?: string;\n}\n\nexport const AGENTS = {\n amp: {\n name: 'amp',\n displayName: 'Amp',\n skillsDir: '.agents/skills',\n globalSkillsDir: join(configHome, 'agents/skills'),\n },\n antigravity: {\n name: 'antigravity',\n displayName: 'Antigravity',\n skillsDir: '.agent/skills',\n globalSkillsDir: join(home, '.gemini/antigravity/skills'),\n detectMarker: '.agent',\n },\n augment: {\n name: 'augment',\n displayName: 'Augment',\n skillsDir: '.augment/skills',\n globalSkillsDir: join(home, '.augment/skills'),\n detectMarker: '.augment',\n },\n 'claude-code': {\n name: 'claude-code',\n displayName: 'Claude Code',\n skillsDir: '.claude/skills',\n globalSkillsDir: join(claudeHome, 'skills'),\n detectMarker: '.claude',\n },\n openclaw: {\n name: 'openclaw',\n displayName: 'OpenClaw',\n skillsDir: 'skills',\n globalSkillsDir: join(home, '.openclaw/skills'),\n },\n cline: {\n name: 'cline',\n displayName: 'Cline',\n skillsDir: '.cline/skills',\n globalSkillsDir: join(home, '.cline/skills'),\n detectMarker: '.cline',\n },\n codebuddy: {\n name: 'codebuddy',\n displayName: 'CodeBuddy',\n skillsDir: '.codebuddy/skills',\n globalSkillsDir: join(home, '.codebuddy/skills'),\n detectMarker: '.codebuddy',\n },\n codex: {\n name: 'codex',\n displayName: 'Codex',\n skillsDir: '.agents/skills',\n globalSkillsDir: join(codexHome, 'skills'),\n },\n 'command-code': {\n name: 'command-code',\n displayName: 'Command Code',\n skillsDir: '.commandcode/skills',\n globalSkillsDir: join(home, '.commandcode/skills'),\n detectMarker: '.commandcode',\n },\n continue: {\n name: 'continue',\n displayName: 'Continue',\n skillsDir: '.continue/skills',\n globalSkillsDir: join(home, '.continue/skills'),\n detectMarker: '.continue',\n },\n crush: {\n name: 'crush',\n displayName: 'Crush',\n skillsDir: '.crush/skills',\n globalSkillsDir: join(home, '.config/crush/skills'),\n },\n cursor: {\n name: 'cursor',\n displayName: 'Cursor',\n skillsDir: '.cursor/skills',\n globalSkillsDir: join(home, '.cursor/skills'),\n detectMarker: '.cursor',\n },\n droid: {\n name: 'droid',\n displayName: 'Droid',\n skillsDir: '.factory/skills',\n globalSkillsDir: join(home, '.factory/skills'),\n detectMarker: '.factory',\n },\n 'gemini-cli': {\n name: 'gemini-cli',\n displayName: 'Gemini CLI',\n skillsDir: '.agents/skills',\n globalSkillsDir: join(home, '.gemini/skills'),\n },\n 'github-copilot': {\n name: 'github-copilot',\n displayName: 'GitHub Copilot',\n skillsDir: '.agents/skills',\n globalSkillsDir: join(home, '.copilot/skills'),\n },\n goose: {\n name: 'goose',\n displayName: 'Goose',\n skillsDir: '.goose/skills',\n globalSkillsDir: join(configHome, 'goose/skills'),\n detectMarker: '.goose',\n },\n junie: {\n name: 'junie',\n displayName: 'Junie',\n skillsDir: '.junie/skills',\n globalSkillsDir: join(home, '.junie/skills'),\n detectMarker: '.junie',\n },\n 'iflow-cli': {\n name: 'iflow-cli',\n displayName: 'iFlow CLI',\n skillsDir: '.iflow/skills',\n globalSkillsDir: join(home, '.iflow/skills'),\n detectMarker: '.iflow',\n },\n kilo: {\n name: 'kilo',\n displayName: 'Kilo Code',\n skillsDir: '.kilocode/skills',\n globalSkillsDir: join(home, '.kilocode/skills'),\n detectMarker: '.kilocode',\n },\n 'kimi-cli': {\n name: 'kimi-cli',\n displayName: 'Kimi Code CLI',\n skillsDir: '.agents/skills',\n globalSkillsDir: join(home, '.config/agents/skills'),\n },\n 'kiro-cli': {\n name: 'kiro-cli',\n displayName: 'Kiro CLI',\n skillsDir: '.kiro/skills',\n globalSkillsDir: join(home, '.kiro/skills'),\n detectMarker: '.kiro',\n },\n kode: {\n name: 'kode',\n displayName: 'Kode',\n skillsDir: '.kode/skills',\n globalSkillsDir: join(home, '.kode/skills'),\n detectMarker: '.kode',\n },\n mcpjam: {\n name: 'mcpjam',\n displayName: 'MCPJam',\n skillsDir: '.mcpjam/skills',\n globalSkillsDir: join(home, '.mcpjam/skills'),\n detectMarker: '.mcpjam',\n },\n 'mistral-vibe': {\n name: 'mistral-vibe',\n displayName: 'Mistral Vibe',\n skillsDir: '.vibe/skills',\n globalSkillsDir: join(home, '.vibe/skills'),\n detectMarker: '.vibe',\n },\n mux: {\n name: 'mux',\n displayName: 'Mux',\n skillsDir: '.mux/skills',\n globalSkillsDir: join(home, '.mux/skills'),\n detectMarker: '.mux',\n },\n opencode: {\n name: 'opencode',\n displayName: 'OpenCode',\n skillsDir: '.opencode/skills',\n globalSkillsDir: join(configHome, 'opencode/skills'),\n },\n openhands: {\n name: 'openhands',\n displayName: 'OpenHands',\n skillsDir: '.openhands/skills',\n globalSkillsDir: join(home, '.openhands/skills'),\n detectMarker: '.openhands',\n },\n pi: {\n name: 'pi',\n displayName: 'Pi',\n skillsDir: '.pi/skills',\n globalSkillsDir: join(home, '.pi/agent/skills'),\n detectMarker: '.pi',\n },\n qoder: {\n name: 'qoder',\n displayName: 'Qoder',\n skillsDir: '.qoder/skills',\n globalSkillsDir: join(home, '.qoder/skills'),\n detectMarker: '.qoder',\n },\n 'qwen-code': {\n name: 'qwen-code',\n displayName: 'Qwen Code',\n skillsDir: '.qwen/skills',\n globalSkillsDir: join(home, '.qwen/skills'),\n detectMarker: '.qwen',\n },\n replit: {\n name: 'replit',\n displayName: 'Replit',\n skillsDir: '.agents/skills',\n globalSkillsDir: join(configHome, 'agents/skills'),\n },\n roo: {\n name: 'roo',\n displayName: 'Roo Code',\n skillsDir: '.roo/skills',\n globalSkillsDir: join(home, '.roo/skills'),\n detectMarker: '.roo',\n },\n trae: {\n name: 'trae',\n displayName: 'Trae',\n skillsDir: '.trae/skills',\n globalSkillsDir: join(home, '.trae/skills'),\n detectMarker: '.trae',\n },\n 'trae-cn': {\n name: 'trae-cn',\n displayName: 'Trae CN',\n skillsDir: '.trae/skills',\n globalSkillsDir: join(home, '.trae-cn/skills'),\n },\n windsurf: {\n name: 'windsurf',\n displayName: 'Windsurf',\n skillsDir: '.windsurf/skills',\n globalSkillsDir: join(home, '.codeium/windsurf/skills'),\n detectMarker: '.windsurf',\n },\n zencoder: {\n name: 'zencoder',\n displayName: 'Zencoder',\n skillsDir: '.zencoder/skills',\n globalSkillsDir: join(home, '.zencoder/skills'),\n detectMarker: '.zencoder',\n },\n neovate: {\n name: 'neovate',\n displayName: 'Neovate',\n skillsDir: '.neovate/skills',\n globalSkillsDir: join(home, '.neovate/skills'),\n detectMarker: '.neovate',\n },\n pochi: {\n name: 'pochi',\n displayName: 'Pochi',\n skillsDir: '.pochi/skills',\n globalSkillsDir: join(home, '.pochi/skills'),\n detectMarker: '.pochi',\n },\n adal: {\n name: 'adal',\n displayName: 'AdaL',\n skillsDir: '.adal/skills',\n globalSkillsDir: join(home, '.adal/skills'),\n detectMarker: '.adal',\n },\n} as const satisfies Record<string, AgentConfig>;\n\nexport type AgentPlatform = keyof typeof AGENTS;\n\n/** Get config for a specific agent */\nexport function getAgentConfig(type: AgentPlatform): AgentConfig {\n return AGENTS[type];\n}\n\n/** List all supported platform keys */\nexport function getSupportedPlatforms(): AgentPlatform[] {\n return Object.keys(AGENTS) as AgentPlatform[];\n}\n\n/** Detect current platform by checking cwd for directory markers */\nexport function detectPlatform(cwd: string): AgentPlatform {\n for (const [key, config] of Object.entries(AGENTS) as Array<[AgentPlatform, AgentConfig]>) {\n if (config.detectMarker && existsSync(join(cwd, config.detectMarker))) {\n return key;\n }\n }\n\n // Fallback: check opencode via global config\n if (existsSync(join(configHome, 'opencode'))) {\n return 'opencode';\n }\n\n return 'claude-code';\n}\n\n/** Get the project-level skills directory name for an agent */\nexport function getAgentSkillsDir(platform: AgentPlatform): string {\n return AGENTS[platform].skillsDir;\n}\n\n/** Get full skill installation path: cwd + skillsDir + skillName */\nexport function getAgentSkillPath(cwd: string, agent: AgentPlatform, name: string): string {\n return join(cwd, AGENTS[agent].skillsDir, name);\n}\n\n/** Get the agent skills root directory: cwd + skillsDir */\nexport function getAgentSkillsRoot(cwd: string, agent: AgentPlatform): string {\n return join(cwd, AGENTS[agent].skillsDir);\n}\n","import { existsSync } from 'node:fs';\nimport { REGISTRY_PATH } from '../utils/paths.js';\nimport { atomicWriteJson, readJsonSafe } from '../utils/fs-helpers.js';\nimport { RegistryCorruptError } from '../utils/errors.js';\nimport type { Registry, RegistryEntry } from '../types/index.js';\n\n/** Create an empty registry */\nfunction createEmptyRegistry(): Registry {\n return { version: 1, skills: {} };\n}\n\n/** Validate registry structure */\nfunction validateRegistry(data: unknown): data is Registry {\n if (!data || typeof data !== 'object') return false;\n const reg = data as Record<string, unknown>;\n return reg.version === 1 && typeof reg.skills === 'object' && reg.skills !== null;\n}\n\n/** Read the registry, creating a new one if it doesn't exist */\nexport async function readRegistry(): Promise<Registry> {\n if (!existsSync(REGISTRY_PATH)) {\n return createEmptyRegistry();\n }\n\n const data = await readJsonSafe<Registry>(REGISTRY_PATH);\n if (!data) {\n throw new RegistryCorruptError('Failed to parse registry.json');\n }\n\n if (!validateRegistry(data)) {\n throw new RegistryCorruptError('Invalid registry structure');\n }\n\n return data;\n}\n\n/** Update or add a skill entry in the registry (atomic write) */\nexport async function updateRegistry(\n skillName: string,\n entry: RegistryEntry,\n): Promise<void> {\n const registry = await readRegistry();\n registry.skills[skillName] = entry;\n await atomicWriteJson(REGISTRY_PATH, registry);\n}\n\n/** Remove a skill from the registry */\nexport async function removeFromRegistry(skillName: string): Promise<void> {\n const registry = await readRegistry();\n delete registry.skills[skillName];\n await atomicWriteJson(REGISTRY_PATH, registry);\n}\n\n/** List all registered skills */\nexport async function listRegistry(): Promise<Record<string, RegistryEntry>> {\n const registry = await readRegistry();\n return registry.skills;\n}\n\n/** Get a single registry entry */\nexport async function getRegistryEntry(skillName: string): Promise<RegistryEntry | null> {\n const registry = await readRegistry();\n return registry.skills[skillName] ?? null;\n}","import { installSkill } from '../core/installer.js';\nimport { isGitUrl } from '../core/git-source.js';\nimport * as logger from '../utils/logger.js';\nimport type { SkillSource, AgentPlatform } from '../types/index.js';\n\nexport interface AddFlags {\n global: boolean;\n agent: string[];\n skill: string[];\n yes: boolean;\n list: boolean;\n all: boolean;\n fullDepth: boolean;\n copy: boolean;\n force: boolean;\n}\n\n/**\n * Parse POSIX-style flags for the add command.\n * Supports: -g/--global, -a/--agent, -s/--skill, -y/--yes,\n * -l/--list, --all, --full-depth, --copy, --force\n */\nexport function parseAddFlags(args: string[]): { source: string | null; flags: AddFlags } {\n const flags: AddFlags = {\n global: false,\n agent: [],\n skill: [],\n yes: false,\n list: false,\n all: false,\n fullDepth: false,\n copy: false,\n force: false,\n };\n\n let source: string | null = null;\n let i = 0;\n\n while (i < args.length) {\n const arg = args[i];\n\n // Long flags with = syntax (backward compat: --agent=claude-code)\n if (arg.startsWith('--') && arg.includes('=')) {\n const eqIdx = arg.indexOf('=');\n const key = arg.slice(2, eqIdx);\n const val = arg.slice(eqIdx + 1);\n switch (key) {\n case 'agent': flags.agent.push(val); break;\n case 'skill': flags.skill.push(val); break;\n default: break;\n }\n i++;\n continue;\n }\n\n switch (arg) {\n case '-g':\n case '--global':\n flags.global = true;\n i++;\n break;\n\n case '-a':\n case '--agent':\n // Consume following non-flag args as agent names\n i++;\n while (i < args.length && !args[i].startsWith('-')) {\n flags.agent.push(args[i]);\n i++;\n }\n break;\n\n case '-s':\n case '--skill':\n // Consume following non-flag args as skill names\n i++;\n while (i < args.length && !args[i].startsWith('-')) {\n flags.skill.push(args[i]);\n i++;\n }\n break;\n\n case '-y':\n case '--yes':\n flags.yes = true;\n i++;\n break;\n\n case '-l':\n case '--list':\n flags.list = true;\n i++;\n break;\n\n case '--all':\n flags.all = true;\n i++;\n break;\n\n case '--full-depth':\n flags.fullDepth = true;\n i++;\n break;\n\n case '--copy':\n flags.copy = true;\n i++;\n break;\n\n case '--force':\n flags.force = true;\n i++;\n break;\n\n default:\n // First non-flag argument is the source\n if (!arg.startsWith('-') && source === null) {\n source = arg;\n }\n i++;\n break;\n }\n }\n\n // --all implies --skill '*' --agent '*' -y\n if (flags.all) {\n if (flags.skill.length === 0) flags.skill.push('*');\n if (flags.agent.length === 0) flags.agent.push('*');\n flags.yes = true;\n }\n\n return { source, flags };\n}\n\n/** add command — install skills (compatible with `npx skills add`) */\nexport async function add(args: string[]): Promise<void> {\n if (args.length === 0) {\n logger.error('Usage: skill-master add <source> [options]');\n console.log('');\n console.log('Options:');\n console.log(' -g, --global Install globally (~/.agents/)');\n console.log(' -a, --agent <agents> Target agents (space-separated)');\n console.log(' -s, --skill <skills> Select skills (space-separated)');\n console.log(' -y, --yes Skip confirmations');\n console.log(' -l, --list List available skills without installing');\n console.log(' --all Install all skills to all agents');\n console.log(' --full-depth Search all subdirectories');\n console.log(' --copy Copy instead of symlink');\n console.log(' --force Force reinstall');\n process.exit(1);\n }\n\n const { source, flags } = parseAddFlags(args);\n\n if (!source) {\n logger.error('No source specified. Provide a GitHub URL, owner/repo, or local path.');\n process.exit(1);\n }\n\n const skillSource: SkillSource = isGitUrl(source)\n ? { type: 'git', url: source }\n : { type: 'local', path: source };\n\n const cwd = process.cwd();\n\n // If multiple agents specified, install for each\n const agents = flags.agent.length > 0 ? flags.agent : [undefined];\n\n try {\n for (const agent of agents) {\n await installSkill({\n source: skillSource,\n agent: agent as AgentPlatform | undefined,\n cwd,\n copy: flags.copy,\n force: flags.force,\n yes: flags.yes,\n });\n }\n } catch (err) {\n logger.error((err as Error).message);\n process.exit(1);\n }\n}\n","import { getRegistryEntry } from '../core/registry.js';\nimport { installSkill } from '../core/installer.js';\nimport { isGitUrl } from '../core/git-source.js';\nimport * as logger from '../utils/logger.js';\nimport { SkillNotFoundError } from '../utils/errors.js';\nimport type { SkillSource } from '../types/index.js';\n\nexport async function update(args: string[]): Promise<void> {\n if (args.length === 0) {\n logger.error('Usage: skill-master update <skill-name> [--force]');\n process.exit(1);\n }\n\n const skillName = args[0];\n const force = args.includes('--force');\n\n try {\n const entry = await getRegistryEntry(skillName);\n if (!entry) {\n throw new SkillNotFoundError(skillName);\n }\n\n logger.info(`Updating skill: ${skillName}`);\n logger.info(`Source: ${entry.source}`);\n\n const source: SkillSource = isGitUrl(entry.source)\n ? { type: 'git', url: entry.source }\n : { type: 'local', path: entry.source };\n\n await installSkill({\n source,\n agent: entry.agent,\n cwd: process.cwd(),\n force: true,\n });\n\n logger.success(`Skill \"${skillName}\" updated successfully!`);\n } catch (err) {\n logger.error((err as Error).message);\n process.exit(1);\n }\n}\n","import { getRegistryEntry, removeFromRegistry, listRegistry } from '../core/registry.js';\nimport { removePath } from '../utils/fs-helpers.js';\nimport { getSkillCanonicalPath, getSkillConfigPath } from '../utils/paths.js';\nimport * as logger from '../utils/logger.js';\nimport { SkillNotFoundError } from '../utils/errors.js';\n\nexport interface RemoveFlags {\n global: boolean;\n agent: string[];\n skill: string[];\n yes: boolean;\n all: boolean;\n purge: boolean;\n}\n\n/** Parse POSIX-style flags for the remove command */\nexport function parseRemoveFlags(args: string[]): { names: string[]; flags: RemoveFlags } {\n const flags: RemoveFlags = {\n global: false,\n agent: [],\n skill: [],\n yes: false,\n all: false,\n purge: false,\n };\n\n const names: string[] = [];\n let i = 0;\n\n while (i < args.length) {\n const arg = args[i];\n\n // Long flags with = syntax (backward compat: --agent=claude-code)\n if (arg.startsWith('--') && arg.includes('=')) {\n const eqIdx = arg.indexOf('=');\n const key = arg.slice(2, eqIdx);\n const val = arg.slice(eqIdx + 1);\n switch (key) {\n case 'agent': flags.agent.push(val); break;\n case 'skill': flags.skill.push(val); break;\n default: break;\n }\n i++;\n continue;\n }\n\n switch (arg) {\n case '-g':\n case '--global':\n flags.global = true;\n i++;\n break;\n\n case '-a':\n case '--agent':\n i++;\n while (i < args.length && !args[i].startsWith('-')) {\n flags.agent.push(args[i]);\n i++;\n }\n break;\n\n case '-s':\n case '--skill':\n i++;\n while (i < args.length && !args[i].startsWith('-')) {\n flags.skill.push(args[i]);\n i++;\n }\n break;\n\n case '-y':\n case '--yes':\n flags.yes = true;\n i++;\n break;\n\n case '--all':\n flags.all = true;\n i++;\n break;\n\n case '--purge':\n flags.purge = true;\n i++;\n break;\n\n default:\n // Non-flag arguments are skill names (positional)\n if (!arg.startsWith('-')) {\n names.push(arg);\n }\n i++;\n break;\n }\n }\n\n // --all implies removing all skills with -y\n if (flags.all) {\n flags.yes = true;\n }\n\n return { names, flags };\n}\n\n/** remove command — remove installed skills */\nexport async function remove(args: string[]): Promise<void> {\n if (args.length === 0) {\n logger.error('Usage: skill-master remove [skills...] [options]');\n console.log('');\n console.log('Options:');\n console.log(' -g, --global Remove from global (~/.agents/)');\n console.log(' -a, --agent <agents> Target agents (space-separated)');\n console.log(' -s, --skill <skills> Select skills (space-separated)');\n console.log(' -y, --yes Skip confirmations');\n console.log(' --all Remove all skills');\n console.log(' --purge Also remove config data');\n process.exit(1);\n }\n\n const { names, flags } = parseRemoveFlags(args);\n\n // Determine which skills to remove\n let skillNames: string[];\n if (flags.all) {\n const registry = await listRegistry();\n skillNames = Object.keys(registry);\n } else if (flags.skill.length > 0) {\n skillNames = flags.skill;\n } else {\n skillNames = names;\n }\n\n if (skillNames.length === 0) {\n logger.error('No skills specified. Provide skill names or use --all.');\n process.exit(1);\n }\n\n try {\n for (const skillName of skillNames) {\n const entry = await getRegistryEntry(skillName);\n if (!entry) {\n throw new SkillNotFoundError(skillName);\n }\n\n logger.info(`Removing skill: ${skillName}`);\n\n // Remove agent directory link/copy\n await removePath(entry.agent_path);\n logger.success(`Removed from ${entry.agent_path}`);\n\n // Remove canonical directory\n await removePath(entry.canonical_path);\n logger.success(`Removed from ${entry.canonical_path}`);\n\n // Optionally purge config\n if (flags.purge) {\n await removePath(getSkillConfigPath(skillName));\n logger.success('Purged config directory');\n }\n\n // Update registry\n await removeFromRegistry(skillName);\n logger.success(`Skill \"${skillName}\" removed successfully!`);\n }\n } catch (err) {\n logger.error((err as Error).message);\n process.exit(1);\n }\n}\n","import { listRegistry } from '../core/registry.js';\nimport { getEnvStatus, setEnvValue, getEnvEditPath } from '../core/env-manager.js';\nimport { getSkillCanonicalPath } from '../utils/paths.js';\nimport * as logger from '../utils/logger.js';\nimport { spawn } from 'node:child_process';\n\nexport async function env(args: string[]): Promise<void> {\n const subcommand = args[0];\n\n if (!subcommand || subcommand === 'list') {\n await envList();\n } else if (subcommand === 'set') {\n await envSet(args.slice(1));\n } else if (subcommand === 'edit') {\n await envEdit(args.slice(1));\n } else {\n logger.error('Usage: skill-master env <list|set|edit>');\n process.exit(1);\n }\n}\n\nasync function envList(): Promise<void> {\n const skills = await listRegistry();\n const entries = Object.entries(skills);\n\n if (entries.length === 0) {\n logger.info('No skills installed');\n return;\n }\n\n logger.blank();\n logger.tableHeader('Skill', 'Status', 'Keys');\n\n for (const [name, entry] of entries) {\n const status = await getEnvStatus(name, entry.env_keys);\n const statusIcon = status === 'configured' ? '✓' : status === 'partial' ? '⚠' : '✗';\n logger.tableRow(name, `${statusIcon} ${status}`, entry.env_keys.join(', '));\n }\n logger.blank();\n}\n\nasync function envSet(args: string[]): Promise<void> {\n if (args.length < 2) {\n logger.error('Usage: skill-master env set <skill> KEY=VALUE');\n process.exit(1);\n }\n\n const skillName = args[0];\n const [key, value] = args[1].split('=');\n\n if (!key || !value) {\n logger.error('Invalid format. Use: KEY=VALUE');\n process.exit(1);\n }\n\n try {\n const skillDir = getSkillCanonicalPath(skillName);\n await setEnvValue(skillName, key, value, skillDir);\n logger.success(`Set ${key} for ${skillName}`);\n } catch (err) {\n logger.error((err as Error).message);\n process.exit(1);\n }\n}\n\nasync function envEdit(args: string[]): Promise<void> {\n if (args.length === 0) {\n logger.error('Usage: skill-master env edit <skill>');\n process.exit(1);\n }\n\n const skillName = args[0];\n const envPath = getEnvEditPath(skillName);\n const editor = process.env.EDITOR || 'vi';\n\n logger.info(`Opening ${envPath} with ${editor}...`);\n\n const child = spawn(editor, [envPath], {\n stdio: 'inherit',\n shell: true,\n });\n\n child.on('exit', (code) => {\n if (code === 0) {\n logger.success('Saved');\n } else {\n logger.error('Editor exited with error');\n process.exit(1);\n }\n });\n}\n","import { listRegistry } from '../core/registry.js';\nimport * as logger from '../utils/logger.js';\n\nexport interface ListFlags {\n global: boolean;\n agent: string[];\n}\n\n/** Parse flags for the list command */\nexport function parseListFlags(args: string[]): ListFlags {\n const flags: ListFlags = {\n global: false,\n agent: [],\n };\n\n let i = 0;\n while (i < args.length) {\n const arg = args[i];\n\n if (arg.startsWith('--') && arg.includes('=')) {\n const eqIdx = arg.indexOf('=');\n const key = arg.slice(2, eqIdx);\n const val = arg.slice(eqIdx + 1);\n if (key === 'agent') flags.agent.push(val);\n i++;\n continue;\n }\n\n switch (arg) {\n case '-g':\n case '--global':\n flags.global = true;\n i++;\n break;\n case '-a':\n case '--agent':\n i++;\n while (i < args.length && !args[i].startsWith('-')) {\n flags.agent.push(args[i]);\n i++;\n }\n break;\n default:\n i++;\n break;\n }\n }\n\n return flags;\n}\n\n/** list command — list installed skills */\nexport async function list(args: string[] = []): Promise<void> {\n const flags = parseListFlags(args);\n const skills = await listRegistry();\n let entries = Object.entries(skills);\n\n // Filter by agent if specified\n if (flags.agent.length > 0) {\n entries = entries.filter(([, entry]) => flags.agent.includes(entry.agent));\n }\n\n if (entries.length === 0) {\n logger.info('No skills installed');\n return;\n }\n\n logger.blank();\n logger.tableHeader('Skill', 'Version', 'Platform', 'Installed');\n\n for (const [name, entry] of entries) {\n const date = new Date(entry.installed_at).toLocaleDateString();\n logger.tableRow(name, entry.version, entry.agent, date);\n }\n logger.blank();\n}\n","import { getRegistryEntry } from '../core/registry.js';\nimport { getEnvStatus } from '../core/env-manager.js';\nimport * as logger from '../utils/logger.js';\nimport { SkillNotFoundError } from '../utils/errors.js';\n\nexport async function info(args: string[]): Promise<void> {\n if (args.length === 0) {\n logger.error('Usage: skill-master info <skill-name>');\n process.exit(1);\n }\n\n const skillName = args[0];\n\n try {\n const entry = await getRegistryEntry(skillName);\n if (!entry) {\n throw new SkillNotFoundError(skillName);\n }\n\n const envStatus = await getEnvStatus(skillName, entry.env_keys);\n\n logger.blank();\n logger.info(`Skill: ${skillName}`);\n logger.kv('Version', entry.version);\n logger.kv('Platform', entry.agent);\n logger.kv('Source', entry.source);\n logger.kv('Installed', new Date(entry.installed_at).toLocaleString());\n logger.kv('Updated', new Date(entry.updated_at).toLocaleString());\n logger.kv('Canonical Path', entry.canonical_path);\n logger.kv('Agent Path', entry.agent_path);\n logger.kv('Capabilities', entry.capabilities.join(', '));\n logger.kv('Env Keys', entry.env_keys.join(', ') || 'none');\n logger.kv('Env Status', envStatus);\n logger.blank();\n } catch (err) {\n logger.error((err as Error).message);\n process.exit(1);\n }\n}\n","import { existsSync } from 'node:fs';\nimport { listRegistry } from '../core/registry.js';\nimport { getEnvStatus } from '../core/env-manager.js';\nimport { isSymlink } from '../utils/fs-helpers.js';\nimport { AGENTS_HOME, CONFIG_DIR, SKILLS_DIR, REGISTRY_PATH } from '../utils/paths.js';\nimport * as logger from '../utils/logger.js';\n\nexport async function doctor(): Promise<void> {\n logger.blank();\n logger.info('Running diagnostics...');\n logger.blank();\n\n let issues = 0;\n\n // Check directory structure\n logger.info('Checking directory structure...');\n const dirs = [AGENTS_HOME, CONFIG_DIR, SKILLS_DIR];\n for (const dir of dirs) {\n if (existsSync(dir)) {\n logger.success(`✓ ${dir}`);\n } else {\n logger.warn(`✗ ${dir} (missing)`);\n issues++;\n }\n }\n logger.blank();\n\n // Check registry\n logger.info('Checking registry...');\n if (existsSync(REGISTRY_PATH)) {\n logger.success(`✓ ${REGISTRY_PATH}`);\n try {\n const skills = await listRegistry();\n logger.info(` Found ${Object.keys(skills).length} skill(s)`);\n } catch (err) {\n logger.error(`✗ Registry corrupted: ${(err as Error).message}`);\n issues++;\n }\n } else {\n logger.info(` No registry found (will be created on first install)`);\n }\n logger.blank();\n\n // Check each skill\n logger.info('Checking installed skills...');\n try {\n const skills = await listRegistry();\n for (const [name, entry] of Object.entries(skills)) {\n logger.info(`Skill: ${name}`);\n\n // Check canonical path\n if (existsSync(entry.canonical_path)) {\n logger.success(` ✓ Canonical path exists`);\n } else {\n logger.error(` ✗ Canonical path missing: ${entry.canonical_path}`);\n issues++;\n }\n\n // Check agent path\n if (existsSync(entry.agent_path)) {\n const isLink = await isSymlink(entry.agent_path);\n logger.success(` ✓ Agent path exists (${isLink ? 'symlink' : 'copy'})`);\n } else {\n logger.error(` ✗ Agent path missing: ${entry.agent_path}`);\n issues++;\n }\n\n // Check env status\n const envStatus = await getEnvStatus(name, entry.env_keys);\n if (envStatus === 'configured') {\n logger.success(` ✓ Environment configured`);\n } else if (envStatus === 'partial') {\n logger.warn(` ⚠ Environment partially configured`);\n } else if (entry.env_keys.length > 0) {\n logger.warn(` ⚠ Environment not configured`);\n }\n }\n } catch (err) {\n logger.error(`Failed to check skills: ${(err as Error).message}`);\n issues++;\n }\n\n logger.blank();\n if (issues === 0) {\n logger.success('All checks passed!');\n } else {\n logger.warn(`Found ${issues} issue(s)`);\n }\n logger.blank();\n}\n","import * as logger from '../utils/logger.js';\n\n/** find command — search for skills from the registry */\nexport async function find(args: string[]): Promise<void> {\n const query = args.filter(a => !a.startsWith('-')).join(' ').trim();\n\n if (!query) {\n console.log('Usage: skill-master find <query>');\n console.log('');\n console.log('Search for skills in the online registry.');\n console.log('');\n console.log('Examples:');\n console.log(' skill-master find git');\n console.log(' skill-master find \"code review\"');\n process.exit(0);\n }\n\n logger.info(`Searching for \"${query}\"...`);\n\n try {\n const url = `https://skills.sh/api/search?q=${encodeURIComponent(query)}`;\n const response = await fetch(url, {\n headers: { 'Accept': 'application/json' },\n signal: AbortSignal.timeout(10_000),\n });\n\n if (!response.ok) {\n logger.error(`Search API returned ${response.status}: ${response.statusText}`);\n process.exit(1);\n }\n\n const data = await response.json() as SearchResult[];\n\n if (!Array.isArray(data) || data.length === 0) {\n logger.info('No skills found matching your query.');\n return;\n }\n\n logger.blank();\n logger.tableHeader('Name', 'Source', 'Installs');\n\n for (const item of data) {\n logger.tableRow(\n item.name ?? '—',\n item.source ?? '—',\n String(item.installs ?? 0),\n );\n }\n logger.blank();\n } catch (err) {\n if ((err as Error).name === 'TimeoutError') {\n logger.error('Search request timed out. Please try again.');\n } else {\n logger.error(`Search failed: ${(err as Error).message}`);\n }\n process.exit(1);\n }\n}\n\ninterface SearchResult {\n name?: string;\n source?: string;\n installs?: number;\n}\n","import { existsSync } from 'node:fs';\nimport { join, basename } from 'node:path';\nimport { ensureDir, writeText } from '../utils/fs-helpers.js';\nimport * as logger from '../utils/logger.js';\n\nconst SKILL_MD_TEMPLATE = `---\nname: {{NAME}}\nversion: 0.1.0\nauthor: \"\"\ndescription: \"\"\nallowed-tools:\n - Read\n - Edit\n - Write\n - Bash\n - Glob\n - Grep\nuser-invocable: true\n---\n\n# {{NAME}}\n\n<!-- Describe what this skill does -->\n`;\n\n/** init command — create a new skill template */\nexport async function init(args: string[]): Promise<void> {\n const nameArg = args.filter(a => !a.startsWith('-'))[0];\n const cwd = process.cwd();\n\n let targetDir: string;\n let skillName: string;\n\n if (nameArg) {\n targetDir = join(cwd, nameArg);\n skillName = nameArg;\n } else {\n targetDir = cwd;\n skillName = basename(cwd);\n }\n\n const skillMdPath = join(targetDir, 'SKILL.md');\n\n if (existsSync(skillMdPath)) {\n logger.error(`SKILL.md already exists at ${skillMdPath}`);\n process.exit(1);\n }\n\n await ensureDir(targetDir);\n\n const content = SKILL_MD_TEMPLATE\n .replace(/\\{\\{NAME\\}\\}/g, skillName);\n\n await writeText(skillMdPath, content);\n logger.success(`Created ${skillMdPath}`);\n logger.info(`Edit the file to configure your skill.`);\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { listRegistry } from '../core/registry.js';\nimport { isGitUrl, parseGitUrl } from '../core/git-source.js';\nimport * as logger from '../utils/logger.js';\n\nconst execFileAsync = promisify(execFile);\n\n/** check command — check for skill updates */\nexport async function check(_args: string[]): Promise<void> {\n const skills = await listRegistry();\n const entries = Object.entries(skills);\n\n if (entries.length === 0) {\n logger.info('No skills installed');\n return;\n }\n\n logger.info('Checking for updates...');\n logger.blank();\n\n let updatable = 0;\n\n for (const [name, entry] of entries) {\n if (!isGitUrl(entry.source)) {\n logger.info(`${name}: local source — skipped`);\n continue;\n }\n\n try {\n const remoteHead = await getRemoteHead(entry.source);\n if (!remoteHead) {\n logger.warn(`${name}: unable to query remote`);\n continue;\n }\n\n // Compare with installed version (stored as git short hash or semver)\n // If version differs from remote HEAD, an update is available\n const isUpToDate = entry.version === remoteHead.slice(0, entry.version.length);\n if (isUpToDate) {\n logger.success(`${name}: up to date (${entry.version})`);\n } else {\n logger.warn(`${name}: update available (${entry.version} → ${remoteHead.slice(0, 7)})`);\n updatable++;\n }\n } catch {\n logger.warn(`${name}: failed to check remote`);\n }\n }\n\n logger.blank();\n if (updatable === 0) {\n logger.success('All skills are up to date!');\n } else {\n logger.info(`${updatable} skill(s) can be updated. Run \"skill-master update <name>\" to update.`);\n }\n}\n\n/** Get the latest commit hash from a remote git repo */\nasync function getRemoteHead(source: string): Promise<string | null> {\n try {\n const { owner, repo } = parseGitUrl(source);\n const url = `https://github.com/${owner}/${repo}.git`;\n const { stdout } = await execFileAsync('git', ['ls-remote', url, 'HEAD'], {\n timeout: 15_000,\n });\n const match = stdout.trim().split(/\\s+/)[0];\n return match || null;\n } catch {\n return null;\n }\n}\n","#!/usr/bin/env node\n\nimport { add } from './commands/add.js';\nimport { update } from './commands/update.js';\nimport { remove } from './commands/remove.js';\nimport { env } from './commands/env.js';\nimport { list } from './commands/list.js';\nimport { info } from './commands/info.js';\nimport { doctor } from './commands/doctor.js';\nimport { find } from './commands/find.js';\nimport { init } from './commands/init.js';\nimport { check } from './commands/check.js';\nimport * as logger from './utils/logger.js';\n\nconst VERSION = '0.1.0';\n\nconst HELP = `\nskill-master v${VERSION}\n\nUsage:\n skill-master add <source> [options] Install skills (aliases: install, a, i)\n skill-master remove [skills...] [opts] Remove skills (aliases: rm, r)\n skill-master list [options] List installed skills (alias: ls)\n skill-master find [query] Search for skills (aliases: search, f, s)\n skill-master update [skill] Update skills (alias: upgrade)\n skill-master init [name] Create a new skill template\n skill-master check Check for skill updates\n skill-master env <list|set|edit> Manage environment variables\n skill-master info <skill-name> Show skill details\n skill-master doctor Run diagnostics\n\nAdd Options:\n -g, --global Install globally (~/.agents/)\n -a, --agent <agents> Target agents (space-separated)\n -s, --skill <skills> Select skills (space-separated)\n -y, --yes Skip confirmations\n -l, --list List available skills without installing\n --all Install all skills to all agents\n --full-depth Search all subdirectories\n --copy Copy instead of symlink\n --force Force reinstall\n\nExamples:\n skill-master add owner/repo\n skill-master add https://github.com/user/skill -a claude-code cursor -y\n skill-master add ./local-skill --agent=cursor --copy\n skill-master remove my-skill --purge\n skill-master find \"code review\"\n skill-master init my-new-skill\n skill-master check\n`;\n\nasync function main() {\n const args = process.argv.slice(2);\n\n if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {\n console.log(HELP);\n process.exit(0);\n }\n\n if (args[0] === '--version' || args[0] === '-v') {\n console.log(VERSION);\n process.exit(0);\n }\n\n const command = args[0];\n const commandArgs = args.slice(1);\n\n try {\n switch (command) {\n // add (primary) with aliases: install, a, i\n case 'add':\n case 'a':\n case 'install':\n case 'i':\n await add(commandArgs);\n break;\n\n // remove with aliases: rm, r\n case 'remove':\n case 'rm':\n case 'r':\n await remove(commandArgs);\n break;\n\n // list with alias: ls\n case 'list':\n case 'ls':\n await list(commandArgs);\n break;\n\n // find with aliases: search, f, s\n case 'find':\n case 'search':\n case 'f':\n case 's':\n await find(commandArgs);\n break;\n\n // update with alias: upgrade\n case 'update':\n case 'upgrade':\n await update(commandArgs);\n break;\n\n // init\n case 'init':\n await init(commandArgs);\n break;\n\n // check\n case 'check':\n await check(commandArgs);\n break;\n\n // env, info, doctor — skill-master extensions\n case 'env':\n await env(commandArgs);\n break;\n case 'info':\n await info(commandArgs);\n break;\n case 'doctor':\n await doctor();\n break;\n\n default:\n logger.error(`Unknown command: ${command}`);\n console.log(HELP);\n process.exit(1);\n }\n } catch (err) {\n logger.error((err as Error).message);\n if (process.env.DEBUG) {\n console.error(err);\n }\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":["join","existsSync","existsSync","join","existsSync","existsSync","join","join","homedir","join","existsSync","join","existsSync","join","join","join","homedir","join","existsSync","existsSync","existsSync","join","info","existsSync","existsSync","existsSync","join","join","existsSync","execFile","promisify","execFileAsync","promisify","execFile","info"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skill-master",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Cross-platform skill package manager for AI coding agents",
5
5
  "type": "module",
6
6
  "main": "./dist/cli.js",