skillpkg-cli 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,122 @@
1
+ /**
2
+ * migrate command - Migrate from v1.x to v2.0
3
+ *
4
+ * Generates skillpkg.json and state.json from existing v1.x store.
5
+ */
6
+ import { existsSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { createConfigManager, createStateManager, createLocalStore, } from 'skillpkg-core';
9
+ import { logger, colors, withSpinner } from '../ui/index.js';
10
+ /**
11
+ * migrate command handler
12
+ */
13
+ export async function migrateCommand(options) {
14
+ const cwd = process.cwd();
15
+ const storeDir = join(cwd, '.skillpkg');
16
+ const skillpkgJsonPath = join(cwd, 'skillpkg.json');
17
+ const stateJsonPath = join(storeDir, 'state.json');
18
+ logger.header('Migrate to skillpkg v2.0');
19
+ // Check if v1.x store exists
20
+ if (!existsSync(storeDir)) {
21
+ logger.error('No .skillpkg directory found');
22
+ logger.log('Nothing to migrate. Use `skillpkg init` to create a new project.');
23
+ process.exit(1);
24
+ }
25
+ // Check if already migrated
26
+ if (existsSync(skillpkgJsonPath) && !options.force) {
27
+ logger.warn('skillpkg.json already exists');
28
+ logger.log(`Use ${colors.cyan('--force')} to overwrite`);
29
+ process.exit(1);
30
+ }
31
+ if (existsSync(stateJsonPath) && !options.force) {
32
+ logger.warn('state.json already exists');
33
+ logger.log(`Use ${colors.cyan('--force')} to overwrite`);
34
+ process.exit(1);
35
+ }
36
+ // Get existing skills from v1.x store
37
+ const store = createLocalStore();
38
+ if (!(await store.isInitialized())) {
39
+ logger.error('Store is not properly initialized');
40
+ logger.log('Run `skillpkg init` to create a new project.');
41
+ process.exit(1);
42
+ }
43
+ const skills = await store.listSkills();
44
+ if (skills.length === 0) {
45
+ logger.warn('No skills found in store');
46
+ logger.log('Creating empty skillpkg.json...');
47
+ }
48
+ else {
49
+ logger.log(`Found ${colors.cyan(String(skills.length))} skill(s) to migrate`);
50
+ }
51
+ if (options.dryRun) {
52
+ logger.blank();
53
+ logger.warn('Dry run mode - no changes will be made');
54
+ logger.blank();
55
+ // Show what would be created
56
+ logger.log('Would create:');
57
+ logger.item(`${colors.cyan('skillpkg.json')} - Project configuration`);
58
+ logger.item(`${colors.cyan('.skillpkg/state.json')} - Dependency state`);
59
+ if (skills.length > 0) {
60
+ logger.blank();
61
+ logger.log('Skills to include:');
62
+ for (const skill of skills) {
63
+ logger.item(`${colors.cyan(skill.name)} v${skill.version}`);
64
+ }
65
+ }
66
+ logger.blank();
67
+ return;
68
+ }
69
+ // Create skillpkg.json
70
+ const configManager = createConfigManager();
71
+ const stateManager = createStateManager();
72
+ const newConfig = {
73
+ name: 'migrated-project',
74
+ version: '1.0.0',
75
+ skills: {},
76
+ mcp: {},
77
+ sync_targets: {
78
+ 'claude-code': true,
79
+ },
80
+ };
81
+ // Add skills to config (skills is Record<string, string> - name -> source)
82
+ for (const skill of skills) {
83
+ // Determine source from registry entry
84
+ const entry = await store.getSkillEntry(skill.name);
85
+ const source = entry?.sourceUrl || `local:.skillpkg/skills/${skill.name}`;
86
+ // newConfig.skills is optional, but we initialized it above
87
+ if (newConfig.skills) {
88
+ newConfig.skills[skill.name] = source;
89
+ }
90
+ }
91
+ await withSpinner('Creating skillpkg.json', async () => {
92
+ await configManager.saveProjectConfig(cwd, newConfig);
93
+ });
94
+ // Create state.json
95
+ await withSpinner('Creating state.json', async () => {
96
+ // Initialize empty state first
97
+ await stateManager.loadState(cwd);
98
+ // Record each skill as installed by "user" (since they were manually installed in v1.x)
99
+ for (const skill of skills) {
100
+ const entry = await store.getSkillEntry(skill.name);
101
+ const source = entry?.sourceUrl || `local:.skillpkg/skills/${skill.name}`;
102
+ await stateManager.recordSkillInstall(cwd, skill.name, {
103
+ version: skill.version,
104
+ source,
105
+ installed_by: 'user',
106
+ });
107
+ }
108
+ });
109
+ logger.blank();
110
+ logger.success('Migration complete!');
111
+ logger.blank();
112
+ logger.log('Created files:');
113
+ logger.item(`${colors.cyan('skillpkg.json')} - Project configuration`);
114
+ logger.item(`${colors.cyan('.skillpkg/state.json')} - Dependency state`);
115
+ logger.blank();
116
+ logger.log('Next steps:');
117
+ logger.item(`Edit ${colors.cyan('skillpkg.json')} to customize your project`);
118
+ logger.item(`Run ${colors.cyan('skillpkg sync')} to sync skills to platforms`);
119
+ logger.item(`Run ${colors.cyan('skillpkg status')} to see project status`);
120
+ logger.blank();
121
+ }
122
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ interface StatusOptions {
2
+ json?: boolean;
3
+ }
4
+ /**
5
+ * status command handler
6
+ */
7
+ export declare function statusCommand(options: StatusOptions): Promise<void>;
8
+ export {};
9
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAcA,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAgCD;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAuLzE"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * status command - Show overall project status
3
+ *
4
+ * v2.0: Shows skills, MCP, and sync status
5
+ */
6
+ import { existsSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { createStateManager, createConfigManager, getImplementedTargets, } from 'skillpkg-core';
9
+ import { logger, colors } from '../ui/index.js';
10
+ /**
11
+ * status command handler
12
+ */
13
+ export async function statusCommand(options) {
14
+ const cwd = process.cwd();
15
+ const stateManager = createStateManager();
16
+ const configManager = createConfigManager();
17
+ // Load state and config
18
+ const state = await stateManager.loadState(cwd);
19
+ const config = await configManager.loadProjectConfig(cwd);
20
+ // Build status output
21
+ const output = {
22
+ project: {
23
+ name: config?.name || null,
24
+ configExists: config !== null,
25
+ stateExists: Object.keys(state.skills).length > 0,
26
+ },
27
+ skills: {
28
+ total: 0,
29
+ userInstalled: 0,
30
+ transitive: 0,
31
+ list: [],
32
+ },
33
+ mcp: {
34
+ configured: 0,
35
+ list: [],
36
+ },
37
+ sync: {
38
+ targetsEnabled: [],
39
+ lastSync: {},
40
+ },
41
+ };
42
+ // Skills info
43
+ for (const [name, skillState] of Object.entries(state.skills)) {
44
+ output.skills.total++;
45
+ if (skillState.installed_by === 'user') {
46
+ output.skills.userInstalled++;
47
+ }
48
+ else {
49
+ output.skills.transitive++;
50
+ }
51
+ output.skills.list.push({
52
+ name,
53
+ version: skillState.version,
54
+ installedBy: skillState.installed_by,
55
+ source: skillState.source,
56
+ });
57
+ }
58
+ // MCP info
59
+ if (config?.mcp) {
60
+ for (const [name, mcpConfig] of Object.entries(config.mcp)) {
61
+ output.mcp.configured++;
62
+ output.mcp.list.push({
63
+ name,
64
+ command: mcpConfig.command || mcpConfig.package,
65
+ });
66
+ }
67
+ }
68
+ // Sync info
69
+ if (config?.sync_targets) {
70
+ output.sync.targetsEnabled = Object.entries(config.sync_targets)
71
+ .filter(([_, enabled]) => enabled)
72
+ .map(([name]) => name);
73
+ }
74
+ // Get sync history from state
75
+ if (state.sync_history) {
76
+ for (const [target, timestamp] of Object.entries(state.sync_history)) {
77
+ output.sync.lastSync[target] = timestamp
78
+ ? new Date(timestamp).toLocaleString()
79
+ : null;
80
+ }
81
+ }
82
+ if (options.json) {
83
+ console.log(JSON.stringify(output, null, 2));
84
+ return;
85
+ }
86
+ // Human-readable output
87
+ logger.header('skillpkg Status');
88
+ logger.blank();
89
+ // Project section
90
+ logger.log(colors.bold('Project'));
91
+ if (config) {
92
+ logger.item(`Name: ${colors.cyan(config.name)}`);
93
+ logger.item(`Config: ${colors.green('skillpkg.json found')}`);
94
+ }
95
+ else {
96
+ logger.item(`Config: ${colors.yellow('No skillpkg.json')}`);
97
+ logger.log(` Run ${colors.cyan('skillpkg init')} to create one`);
98
+ }
99
+ logger.blank();
100
+ // Skills section
101
+ logger.log(colors.bold('Skills'));
102
+ if (output.skills.total === 0) {
103
+ logger.item(colors.dim('No skills installed'));
104
+ logger.log(` Run ${colors.cyan('skillpkg install <skill>')} to install`);
105
+ }
106
+ else {
107
+ logger.item(`Total: ${colors.cyan(String(output.skills.total))} ` +
108
+ `(${output.skills.userInstalled} direct, ${output.skills.transitive} transitive)`);
109
+ // List skills grouped by install type
110
+ const userSkills = output.skills.list.filter((s) => s.installedBy === 'user');
111
+ const transitiveSkills = output.skills.list.filter((s) => s.installedBy !== 'user');
112
+ if (userSkills.length > 0) {
113
+ logger.log(' Direct:');
114
+ for (const skill of userSkills) {
115
+ logger.log(` ${colors.cyan(skill.name)} ${colors.dim(`v${skill.version}`)}`);
116
+ }
117
+ }
118
+ if (transitiveSkills.length > 0) {
119
+ logger.log(' Transitive:');
120
+ for (const skill of transitiveSkills) {
121
+ logger.log(` ${colors.dim(skill.name)} ${colors.dim(`v${skill.version}`)} ` +
122
+ colors.dim(`(via ${skill.installedBy})`));
123
+ }
124
+ }
125
+ }
126
+ logger.blank();
127
+ // MCP section
128
+ logger.log(colors.bold('MCP Servers'));
129
+ if (output.mcp.configured === 0) {
130
+ logger.item(colors.dim('No MCP servers configured'));
131
+ }
132
+ else {
133
+ logger.item(`Configured: ${colors.cyan(String(output.mcp.configured))}`);
134
+ for (const mcp of output.mcp.list) {
135
+ logger.log(` ${colors.cyan(mcp.name)}: ${colors.dim(mcp.command)}`);
136
+ }
137
+ }
138
+ logger.blank();
139
+ // Sync section
140
+ logger.log(colors.bold('Sync Targets'));
141
+ const implementedTargets = getImplementedTargets();
142
+ const implementedIds = implementedTargets.map((t) => t.id);
143
+ if (output.sync.targetsEnabled.length === 0) {
144
+ logger.item(colors.dim('No sync targets enabled'));
145
+ }
146
+ else {
147
+ for (const target of output.sync.targetsEnabled) {
148
+ const isImplemented = implementedIds.includes(target);
149
+ const lastSync = output.sync.lastSync[target];
150
+ const status = isImplemented
151
+ ? lastSync
152
+ ? colors.green(`synced ${lastSync}`)
153
+ : colors.yellow('not synced')
154
+ : colors.dim('(not implemented)');
155
+ logger.item(`${colors.cyan(target)}: ${status}`);
156
+ // Check if target directory exists
157
+ const targetConfig = implementedTargets.find((t) => t.id === target);
158
+ if (targetConfig) {
159
+ const targetPath = join(cwd, targetConfig.outputPath);
160
+ const exists = existsSync(targetPath);
161
+ if (!exists) {
162
+ logger.log(` ${colors.dim('Directory not created yet')}`);
163
+ }
164
+ }
165
+ }
166
+ }
167
+ logger.blank();
168
+ // Quick actions
169
+ logger.log(colors.bold('Quick Actions'));
170
+ if (output.skills.total === 0) {
171
+ logger.item(`${colors.cyan('skillpkg search <query>')} - Find skills`);
172
+ logger.item(`${colors.cyan('skillpkg install <skill>')} - Install a skill`);
173
+ }
174
+ else {
175
+ logger.item(`${colors.cyan('skillpkg sync')} - Sync skills to platforms`);
176
+ logger.item(`${colors.cyan('skillpkg tree')} - View dependency tree`);
177
+ }
178
+ logger.blank();
179
+ }
180
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAaA,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CA6If"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAkBA,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CA+Jf"}
@@ -1,162 +1,140 @@
1
1
  /**
2
2
  * sync command - Sync skills to platforms
3
+ *
4
+ * v2.0: Uses new Syncer module from core
3
5
  */
4
- import { createLocalStore, createAdapterManager, parse, } from 'skillpkg-core';
5
- import { readFile } from 'fs/promises';
6
6
  import { join } from 'path';
7
+ import { createSyncer, createConfigManager, loadSkillsFromDirectory, getTargetConfig, getImplementedTargets, } from 'skillpkg-core';
7
8
  import { logger, colors, withSpinner } from '../ui/index.js';
8
9
  /**
9
10
  * sync command handler
10
11
  */
11
12
  export async function syncCommand(skillName, options) {
12
- const store = createLocalStore();
13
- const adapterManager = createAdapterManager();
14
- // Check if store is initialized
15
- if (!(await store.isInitialized())) {
13
+ const cwd = process.cwd();
14
+ const configManager = createConfigManager();
15
+ const syncer = createSyncer();
16
+ // Load project config
17
+ const config = await configManager.loadProjectConfig(cwd);
18
+ // Get skills directory
19
+ const skillsDir = join(cwd, '.skillpkg', 'skills');
20
+ // Load skills from store (returns Map<string, SkillContent>)
21
+ let skills = await loadSkillsFromDirectory(skillsDir);
22
+ if (skills.size === 0) {
16
23
  logger.error('No skills installed');
17
24
  logger.log(`Run ${colors.cyan('skillpkg install <skill>')} first`);
18
25
  process.exit(1);
19
26
  }
20
- // Get skills metadata
21
- const skillsMeta = await store.listSkills();
22
- if (skillsMeta.length === 0) {
23
- logger.info('No skills to sync');
24
- return;
25
- }
26
27
  // Filter by name if provided
27
- const targetSkillsMeta = skillName
28
- ? skillsMeta.filter((s) => s.name === skillName)
29
- : skillsMeta;
30
- if (targetSkillsMeta.length === 0) {
31
- logger.error(`Skill ${colors.cyan(skillName || '')} not found`);
32
- process.exit(1);
33
- }
34
- // Load full skill data
35
- const skills = [];
36
- for (const meta of targetSkillsMeta) {
37
- const skill = await loadSkillContent(meta.name);
38
- if (skill) {
39
- skills.push(skill);
28
+ if (skillName) {
29
+ if (!skills.has(skillName)) {
30
+ logger.error(`Skill ${colors.cyan(skillName)} not found`);
31
+ process.exit(1);
40
32
  }
33
+ const skill = skills.get(skillName);
34
+ skills = new Map([[skillName, skill]]);
41
35
  }
42
- // Parse target platforms
43
- const platforms = options.target
44
- ? options.target.split(',').map((p) => p.trim())
45
- : undefined; // undefined = all platforms
46
36
  logger.header('Sync Skills to Platforms');
47
- // Detect available platforms
48
- const detected = await adapterManager.detectPlatforms(process.cwd());
49
- const presentPlatforms = detected.filter((p) => p.detected);
50
- if (presentPlatforms.length === 0) {
51
- logger.warn('No AI platforms detected in this project');
52
- logger.blank();
53
- logger.log('Supported platforms:');
54
- for (const adapter of adapterManager.listAdapters()) {
55
- logger.item(`${colors.cyan(adapter.displayName)} (${adapter.name})`);
37
+ // Determine targets
38
+ let targetConfigs;
39
+ // Get implemented targets (TargetConfig[])
40
+ const implementedTargets = getImplementedTargets();
41
+ const implementedIds = implementedTargets.map((t) => t.id);
42
+ if (options.target) {
43
+ // User specified targets
44
+ const requestedTargets = options.target.split(',').map((t) => t.trim());
45
+ // Validate target names
46
+ const invalidTargets = requestedTargets.filter((t) => !implementedIds.includes(t));
47
+ if (invalidTargets.length > 0) {
48
+ logger.error(`Unknown or unimplemented targets: ${invalidTargets.join(', ')}`);
49
+ logger.blank();
50
+ logger.log('Available targets:');
51
+ for (const tc of implementedTargets) {
52
+ logger.item(`${colors.cyan(tc.id)} - ${tc.description}`);
53
+ }
54
+ process.exit(1);
56
55
  }
57
- logger.blank();
58
- logger.log('Create platform directories to enable sync:');
59
- logger.item(`${colors.dim('.claude/')} for Claude Code`);
60
- logger.item(`${colors.dim('.codex/')} or ${colors.dim('AGENTS.md')} for Codex`);
61
- logger.item(`${colors.dim('.github/')} for GitHub Copilot`);
62
- logger.item(`${colors.dim('.cline/')} for VS Code Cline`);
63
- logger.blank();
64
- return;
56
+ // Get target configs for valid targets
57
+ targetConfigs = requestedTargets.map((t) => getTargetConfig(t));
65
58
  }
66
- logger.log('Detected platforms:');
67
- for (const platform of presentPlatforms) {
68
- logger.item(`${colors.green('✓')} ${platform.displayName}`);
59
+ else if (config?.sync_targets) {
60
+ // Use targets from config
61
+ const enabledTargets = Object.entries(config.sync_targets)
62
+ .filter(([_, enabled]) => enabled)
63
+ .map(([name]) => name);
64
+ if (enabledTargets.length === 0) {
65
+ logger.warn('No sync targets enabled in skillpkg.json');
66
+ logger.log(`Add targets to ${colors.cyan('sync_targets')} in skillpkg.json`);
67
+ logger.blank();
68
+ logger.log('Available targets:');
69
+ for (const tc of implementedTargets) {
70
+ logger.item(`${colors.cyan(tc.id)} - ${tc.description}`);
71
+ }
72
+ process.exit(1);
73
+ }
74
+ // Filter to only implemented targets
75
+ const validTargets = enabledTargets.filter((t) => implementedIds.includes(t));
76
+ targetConfigs = validTargets.map((t) => getTargetConfig(t));
69
77
  }
78
+ else {
79
+ // Default to claude-code
80
+ targetConfigs = [getTargetConfig('claude-code')];
81
+ logger.warn('No skillpkg.json found, using default target: claude-code');
82
+ }
83
+ logger.log(`Skills to sync: ${colors.cyan(String(skills.size))}`);
84
+ logger.log(`Targets: ${colors.cyan(targetConfigs.map((t) => t.id).join(', '))}`);
70
85
  logger.blank();
71
86
  if (options.dryRun) {
72
87
  logger.warn('Dry run mode - no changes will be made');
73
88
  logger.blank();
74
89
  }
75
- logger.log(`Skills to sync: ${colors.cyan(String(skills.length))}`);
76
- logger.blank();
77
- // Sync
78
- const result = await withSpinner('Syncing skills to platforms', () => adapterManager.sync(skills, {
79
- projectPath: process.cwd(),
80
- platforms,
81
- dryRun: options.dryRun,
82
- }), {
83
- successText: 'Sync complete',
84
- failText: 'Sync failed',
85
- });
90
+ // Sync to each target
91
+ const results = [];
92
+ for (const targetConfig of targetConfigs) {
93
+ const result = await withSpinner(`Syncing to ${targetConfig.displayName}`, async () => {
94
+ return syncer.syncToTarget(cwd, skills, targetConfig, {
95
+ dryRun: options.dryRun,
96
+ });
97
+ }, {
98
+ successText: `Synced to ${targetConfig.displayName}`,
99
+ failText: `Failed to sync to ${targetConfig.displayName}`,
100
+ });
101
+ results.push(result);
102
+ }
86
103
  logger.blank();
87
104
  // Show results
88
- if (result.synced.length > 0) {
89
- logger.success('Synced:');
90
- for (const item of result.synced) {
91
- logger.item(`${colors.cyan(item.skill)} → ${colors.green(item.platform)}`);
92
- logger.log(` ${colors.dim(item.path)}`);
105
+ let totalSynced = 0;
106
+ let totalSkipped = 0;
107
+ let totalErrors = 0;
108
+ for (const result of results) {
109
+ // Count synced files
110
+ const synced = result.files.filter((f) => f.action === 'created' || f.action === 'updated');
111
+ const skipped = result.files.filter((f) => f.action === 'skipped' || f.action === 'unchanged');
112
+ const deleted = result.files.filter((f) => f.action === 'deleted');
113
+ totalSynced += synced.length;
114
+ totalSkipped += skipped.length;
115
+ totalErrors += result.errors?.length || 0;
116
+ if (synced.length > 0) {
117
+ logger.success(`${result.target} (${synced.length} files):`);
118
+ for (const file of synced) {
119
+ const action = file.action === 'created' ? colors.green('+') : colors.yellow('~');
120
+ logger.log(` ${action} ${colors.dim(file.path)}`);
121
+ }
93
122
  }
94
- logger.blank();
95
- }
96
- if (result.skipped.length > 0) {
97
- logger.warn('Skipped:');
98
- for (const item of result.skipped) {
99
- logger.item(`${colors.cyan(item.skill)} → ${colors.yellow(item.platform)}: ${item.reason}`);
123
+ if (deleted.length > 0) {
124
+ logger.log(`${result.target} cleaned ${deleted.length} orphan(s)`);
100
125
  }
101
- logger.blank();
102
- }
103
- if (result.errors.length > 0) {
104
- logger.error('Errors:');
105
- for (const item of result.errors) {
106
- logger.item(`${colors.cyan(item.skill)} → ${colors.red(item.platform)}: ${item.error}`);
126
+ if (result.errors && result.errors.length > 0) {
127
+ logger.error(`${result.target} errors:`);
128
+ for (const error of result.errors) {
129
+ logger.log(` ${colors.red('×')} ${error}`);
130
+ }
107
131
  }
108
- logger.blank();
109
- }
110
- // Update registry with synced platforms
111
- if (!options.dryRun && result.synced.length > 0) {
112
- await updateSyncedPlatformsInRegistry(store, result.synced);
113
132
  }
133
+ logger.blank();
114
134
  // Summary
115
- logger.log(`Summary: ${colors.green(String(result.synced.length))} synced, ` +
116
- `${colors.yellow(String(result.skipped.length))} skipped, ` +
117
- `${colors.red(String(result.errors.length))} errors`);
135
+ logger.log(`Summary: ${colors.green(String(totalSynced))} synced, ` +
136
+ `${colors.yellow(String(totalSkipped))} unchanged, ` +
137
+ `${colors.red(String(totalErrors))} errors`);
118
138
  logger.blank();
119
139
  }
120
- /**
121
- * Load skill content from store
122
- */
123
- async function loadSkillContent(skillName) {
124
- const skillDir = join(process.cwd(), '.skillpkg', 'skills', skillName);
125
- const yamlPath = join(skillDir, 'skill.yaml');
126
- try {
127
- const content = await readFile(yamlPath, 'utf-8');
128
- const result = parse(content);
129
- return result.success && result.data ? result.data : null;
130
- }
131
- catch {
132
- return null;
133
- }
134
- }
135
- /**
136
- * Update synced platforms in registry
137
- */
138
- async function updateSyncedPlatformsInRegistry(store, synced) {
139
- // Group by skill
140
- const bySkill = new Map();
141
- for (const item of synced) {
142
- if (!bySkill.has(item.skill)) {
143
- bySkill.set(item.skill, []);
144
- }
145
- bySkill.get(item.skill).push(item.platform);
146
- }
147
- // Update each skill's synced platforms
148
- for (const [skillName, platforms] of bySkill) {
149
- // Get existing entry to merge platforms
150
- const entry = await store.getSkillEntry(skillName);
151
- if (entry) {
152
- // Merge with existing platforms
153
- const existingPlatforms = new Set(entry.syncedPlatforms || []);
154
- for (const p of platforms) {
155
- existingPlatforms.add(p);
156
- }
157
- // Update using store method
158
- await store.updateSyncedPlatforms(skillName, Array.from(existingPlatforms));
159
- }
160
- }
161
- }
162
140
  //# sourceMappingURL=sync.js.map