@h1dr0n/skill-pool 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h1dr0n/skill-pool",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "CLI tool to install AI coding skills per-project",
5
5
  "type": "module",
6
6
  "bin": {
@@ -4,12 +4,7 @@ import chalk from 'chalk';
4
4
  import yaml from 'js-yaml';
5
5
  import { cloneRepo, isGitAvailable } from '../utils/git.js';
6
6
  import { fileExists, readFileContent, copyDir, removeDir, ensureDir } from '../utils/fs.js';
7
- import {
8
- loadTracker,
9
- saveTracker,
10
- getInstalledVersion,
11
- recordInstall,
12
- } from '../core/tracker.js';
7
+ import { loadTracker, getInstalledVersion } from '../core/tracker.js';
13
8
  import { getAdapter, detectTargets } from '../adapters/index.js';
14
9
 
15
10
  /**
@@ -237,26 +232,9 @@ export async function addCommand(rawUrl, options = {}) {
237
232
  totalFiles += files.length;
238
233
  }
239
234
 
240
- // 10. Update tracker with github source
241
- tracker = recordInstall(tracker, manifest.name, manifest.version, targets);
242
-
243
- // Add source metadata
244
- tracker = {
245
- ...tracker,
246
- installed: {
247
- ...tracker.installed,
248
- [manifest.name]: {
249
- ...tracker.installed[manifest.name],
250
- source: `github:${rawUrl}`,
251
- },
252
- },
253
- };
254
-
255
- await saveTracker(projectDir, tracker);
256
-
257
235
  console.log(
258
236
  chalk.green(` + ${manifest.name}@${manifest.version}`) +
259
- chalk.gray(` (${totalFiles} rules, source: github)`)
237
+ chalk.gray(` (${totalFiles} files, source: github)`)
260
238
  );
261
239
  console.log(chalk.green(`\nInstalled 1 pack for ${targets.join(', ')}.`));
262
240
  } finally {
@@ -1,39 +1,33 @@
1
1
  import chalk from 'chalk';
2
2
  import { resolveDependencies, checkConflicts } from '../core/resolver.js';
3
3
  import { loadManifest } from '../core/manifest.js';
4
- import {
5
- loadTracker,
6
- saveTracker,
7
- getInstalledVersion,
8
- recordInstall,
9
- } from '../core/tracker.js';
10
- import { getAdapter, detectTargets, getAllTargetNames } from '../adapters/index.js';
4
+ import { loadTracker, getInstalledVersion } from '../core/tracker.js';
5
+ import { getAdapter, detectTargets } from '../adapters/index.js';
11
6
 
12
7
  async function resolveTargets(projectDir, targetOption) {
13
8
  if (targetOption) {
14
9
  const names = targetOption.split(',').map((t) => t.trim());
15
- names.forEach((n) => getAdapter(n)); // validate
10
+ names.forEach((n) => getAdapter(n));
16
11
  return names;
17
12
  }
18
13
 
19
14
  const detected = await detectTargets(projectDir);
20
15
  if (detected.length > 0) return detected;
21
16
 
22
- // Default to claude if nothing detected
23
17
  return ['claude'];
24
18
  }
25
19
 
26
20
  export async function installCommand(packNames, options = {}) {
27
21
  const projectDir = process.cwd();
28
22
  const targets = await resolveTargets(projectDir, options.target);
29
- let tracker = await loadTracker(projectDir);
23
+ const tracker = await loadTracker(projectDir);
30
24
 
31
25
  console.log(chalk.gray(`Targets: ${targets.join(', ')}\n`));
32
26
 
33
27
  if (packNames.length > 1) {
34
28
  const conflicts = await checkConflicts(packNames);
35
29
  if (conflicts.length > 0) {
36
- console.log(chalk.yellow('Dependency version conflicts detected:\n'));
30
+ console.log(chalk.yellow('Dependency version conflicts detected:\n'));
37
31
  for (const conflict of conflicts) {
38
32
  console.log(
39
33
  chalk.yellow(
@@ -42,7 +36,7 @@ export async function installCommand(packNames, options = {}) {
42
36
  )
43
37
  );
44
38
  }
45
- console.log(chalk.yellow('\n Using latest version for each conflicting dependency.\n'));
39
+ console.log(chalk.yellow('\n Using latest version for each.\n'));
46
40
  }
47
41
  }
48
42
 
@@ -71,17 +65,13 @@ export async function installCommand(packNames, options = {}) {
71
65
  totalFiles += files.length;
72
66
  }
73
67
 
74
- tracker = recordInstall(tracker, packName, manifest.version, targets);
75
68
  installedCount++;
76
-
77
69
  console.log(
78
70
  chalk.green(` + ${packName}@${manifest.version}`) +
79
- chalk.gray(` (${totalFiles} rules)`)
71
+ chalk.gray(` (${totalFiles} files)`)
80
72
  );
81
73
  }
82
74
 
83
- await saveTracker(projectDir, tracker);
84
-
85
75
  if (installedCount === 0) {
86
76
  console.log(chalk.yellow('\nAll packs already up to date.'));
87
77
  } else {
@@ -1,10 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import {
3
- loadTracker,
4
- saveTracker,
5
- isInstalled,
6
- recordRemove,
7
- } from '../core/tracker.js';
2
+ import { loadTracker, isInstalled, getInstalledTargets } from '../core/tracker.js';
8
3
  import { loadManifest } from '../core/manifest.js';
9
4
  import { getAdapter, getAllTargetNames } from '../adapters/index.js';
10
5
 
@@ -20,18 +15,13 @@ async function findDependents(packName, tracker) {
20
15
  dependents.push(installed);
21
16
  }
22
17
  } catch {
23
- // skip if manifest can't be loaded
18
+ // skip
24
19
  }
25
20
  }
26
21
 
27
22
  return dependents;
28
23
  }
29
24
 
30
- function getTargetsForPack(tracker, packName) {
31
- const info = tracker.installed[packName];
32
- return info?.targets || getAllTargetNames();
33
- }
34
-
35
25
  async function removeFromAllTargets(packName, targets, projectDir) {
36
26
  let totalRemoved = 0;
37
27
  for (const targetName of targets) {
@@ -40,7 +30,7 @@ async function removeFromAllTargets(packName, targets, projectDir) {
40
30
  const removed = await adapter.remove(packName, projectDir);
41
31
  totalRemoved += removed.length;
42
32
  } catch {
43
- // adapter might not have files for this pack
33
+ // adapter might not have files
44
34
  }
45
35
  }
46
36
  return totalRemoved;
@@ -48,7 +38,7 @@ async function removeFromAllTargets(packName, targets, projectDir) {
48
38
 
49
39
  export async function removeCommand(packName, options) {
50
40
  const projectDir = process.cwd();
51
- let tracker = await loadTracker(projectDir);
41
+ const tracker = await loadTracker(projectDir);
52
42
 
53
43
  if (options.all) {
54
44
  const installedPacks = Object.keys(tracker.installed);
@@ -58,15 +48,13 @@ export async function removeCommand(packName, options) {
58
48
  }
59
49
 
60
50
  for (const name of installedPacks) {
61
- const targets = getTargetsForPack(tracker, name);
62
- const count = await removeFromAllTargets(name, targets, projectDir);
63
- tracker = recordRemove(tracker, name);
51
+ const targets = getInstalledTargets(tracker, name);
52
+ const count = await removeFromAllTargets(name, targets.length > 0 ? targets : getAllTargetNames(), projectDir);
64
53
  console.log(
65
- chalk.red(` - ${name}`) + chalk.gray(` (${count} rules removed)`)
54
+ chalk.red(` - ${name}`) + chalk.gray(` (${count} files removed)`)
66
55
  );
67
56
  }
68
57
 
69
- await saveTracker(projectDir, tracker);
70
58
  console.log(chalk.green('\nAll packs removed.'));
71
59
  return;
72
60
  }
@@ -90,12 +78,10 @@ export async function removeCommand(packName, options) {
90
78
  );
91
79
  }
92
80
 
93
- const targets = getTargetsForPack(tracker, packName);
94
- const count = await removeFromAllTargets(packName, targets, projectDir);
95
- tracker = recordRemove(tracker, packName);
96
- await saveTracker(projectDir, tracker);
81
+ const targets = getInstalledTargets(tracker, packName);
82
+ const count = await removeFromAllTargets(packName, targets.length > 0 ? targets : getAllTargetNames(), projectDir);
97
83
 
98
84
  console.log(
99
- chalk.red(` - ${packName}`) + chalk.gray(` (${count} rules removed)`)
85
+ chalk.red(` - ${packName}`) + chalk.gray(` (${count} files removed)`)
100
86
  );
101
87
  }
@@ -1,15 +1,11 @@
1
1
  import chalk from 'chalk';
2
2
  import { loadManifest } from '../core/manifest.js';
3
- import {
4
- loadTracker,
5
- saveTracker,
6
- recordInstall,
7
- } from '../core/tracker.js';
3
+ import { loadTracker, getInstalledTargets } from '../core/tracker.js';
8
4
  import { getAdapter } from '../adapters/index.js';
9
5
 
10
6
  export async function updateCommand(packName) {
11
7
  const projectDir = process.cwd();
12
- let tracker = await loadTracker(projectDir);
8
+ const tracker = await loadTracker(projectDir);
13
9
  const installedPacks = Object.keys(tracker.installed);
14
10
 
15
11
  if (installedPacks.length === 0) {
@@ -28,9 +24,9 @@ export async function updateCommand(packName) {
28
24
  }
29
25
 
30
26
  const manifest = await loadManifest(name);
31
- const targets = info.targets || ['claude'];
27
+ const targets = getInstalledTargets(tracker, name);
28
+ if (targets.length === 0) targets.push('claude');
32
29
 
33
- // Re-install to pick up content changes
34
30
  let totalFiles = 0;
35
31
  for (const targetName of targets) {
36
32
  const adapter = getAdapter(targetName);
@@ -38,7 +34,6 @@ export async function updateCommand(packName) {
38
34
  totalFiles += files.length;
39
35
  }
40
36
 
41
- tracker = recordInstall(tracker, name, manifest.version, targets);
42
37
  updatedCount++;
43
38
 
44
39
  const versionChanged = info.version !== manifest.version;
@@ -48,10 +43,9 @@ export async function updateCommand(packName) {
48
43
 
49
44
  console.log(
50
45
  chalk.green(` ~ ${name}@${label}`) +
51
- chalk.gray(` (${totalFiles} rules)`)
46
+ chalk.gray(` (${totalFiles} files)`)
52
47
  );
53
48
  }
54
49
 
55
- await saveTracker(projectDir, tracker);
56
50
  console.log(chalk.green(`\nUpdated ${updatedCount} pack(s).`));
57
51
  }
@@ -1,24 +1,38 @@
1
- import path from 'node:path';
2
- import { readFileContent, writeFileAtomic, fileExists } from '../utils/fs.js';
3
-
4
- const TRACKER_FILE = '.skillpool.json';
5
-
6
- function defaultTracker() {
7
- return { version: '1.0.0', installed: {} };
8
- }
1
+ import { getAdapter, getAllTargetNames } from '../adapters/index.js';
9
2
 
3
+ /**
4
+ * Scan installed files across all adapters to build tracker state from markers.
5
+ * No .skillpool.json needed.
6
+ */
10
7
  export async function loadTracker(projectDir) {
11
- const filePath = path.join(projectDir, TRACKER_FILE);
12
- if (!(await fileExists(filePath))) {
13
- return defaultTracker();
8
+ const installed = {};
9
+ const targetNames = getAllTargetNames();
10
+
11
+ for (const targetName of targetNames) {
12
+ const adapter = getAdapter(targetName);
13
+ try {
14
+ const items = await adapter.list(projectDir);
15
+ for (const item of items) {
16
+ if (!installed[item.pack]) {
17
+ installed[item.pack] = {
18
+ version: item.version,
19
+ targets: [],
20
+ };
21
+ }
22
+ if (!installed[item.pack].targets.includes(targetName)) {
23
+ installed[item.pack].targets.push(targetName);
24
+ }
25
+ // Use latest version found
26
+ if (item.version > installed[item.pack].version) {
27
+ installed[item.pack].version = item.version;
28
+ }
29
+ }
30
+ } catch {
31
+ // adapter dir doesn't exist, skip
32
+ }
14
33
  }
15
- const content = await readFileContent(filePath);
16
- return JSON.parse(content);
17
- }
18
34
 
19
- export async function saveTracker(projectDir, data) {
20
- const filePath = path.join(projectDir, TRACKER_FILE);
21
- await writeFileAtomic(filePath, JSON.stringify(data, null, 2) + '\n');
35
+ return { installed };
22
36
  }
23
37
 
24
38
  export function isInstalled(trackerData, packName) {
@@ -29,21 +43,6 @@ export function getInstalledVersion(trackerData, packName) {
29
43
  return trackerData.installed[packName]?.version || null;
30
44
  }
31
45
 
32
- export function recordInstall(trackerData, packName, version, targets) {
33
- return {
34
- ...trackerData,
35
- installed: {
36
- ...trackerData.installed,
37
- [packName]: {
38
- version,
39
- installedAt: new Date().toISOString(),
40
- targets,
41
- },
42
- },
43
- };
44
- }
45
-
46
- export function recordRemove(trackerData, packName) {
47
- const { [packName]: _, ...rest } = trackerData.installed;
48
- return { ...trackerData, installed: rest };
46
+ export function getInstalledTargets(trackerData, packName) {
47
+ return trackerData.installed[packName]?.targets || [];
49
48
  }