skillpm 0.0.4 → 0.0.6
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 +6 -2
- package/dist/commands/install.d.ts +1 -1
- package/dist/commands/install.js +18 -46
- package/dist/commands/uninstall.js +8 -10
- package/dist/configs/index.d.ts +21 -0
- package/dist/configs/index.js +126 -0
- package/dist/manifest/schema.d.ts +10 -4
- package/dist/manifest/schema.js +1 -0
- package/dist/scanner/index.js +16 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,12 +21,14 @@ npx skillpm list
|
|
|
21
21
|
npx skillpm init
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
Or install
|
|
24
|
+
Or install the CLI globally:
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
27
|
npm install -g skillpm
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
+
> **Note:** Skills are always workspace-local. This installs the `skillpm` CLI — not skills.
|
|
31
|
+
|
|
30
32
|
## How it works
|
|
31
33
|
|
|
32
34
|
When you run `skillpm install <skill>`:
|
|
@@ -34,7 +36,8 @@ When you run `skillpm install <skill>`:
|
|
|
34
36
|
1. **npm install** — npm handles resolution, download, lockfile, `node_modules/`
|
|
35
37
|
2. **Scan** — skillpm scans `node_modules/` for packages containing `skills/*/SKILL.md`
|
|
36
38
|
3. **Link** — for each skill found, skillpm calls [`skills`](https://www.npmjs.com/package/skills) to wire it into agent directories (Claude, Cursor, VS Code, Codex, and many more)
|
|
37
|
-
4. **
|
|
39
|
+
4. **Configs** — for each skill with a `configs/` directory, skillpm copies agent definitions, rules, and prompts into the workspace (auto-prefixed to avoid conflicts)
|
|
40
|
+
5. **MCP config** — skillpm collects `skillpm.mcpServers` from all skills (transitively) and configures each via [`add-mcp`](https://github.com/neondatabase/add-mcp)
|
|
38
41
|
|
|
39
42
|
That's it. Agents see the full skill tree with MCP servers configured.
|
|
40
43
|
|
|
@@ -49,6 +52,7 @@ skillpm doesn't reinvent anything. It orchestrates three battle-tested tools: np
|
|
|
49
52
|
| Dependency management | Standard `package.json` `dependencies` — npm handles semver, lockfiles, audit |
|
|
50
53
|
| Versioning | npm semver, `package-lock.json`, reproducible installs |
|
|
51
54
|
| Agent wiring | Links skills into agent directories via [`skills`](https://www.npmjs.com/package/skills) |
|
|
55
|
+
| Config files | Copies agent definitions, rules, and prompts from `configs/` into the workspace |
|
|
52
56
|
| MCP server config | Collects and configures MCP servers transitively via [`add-mcp`](https://github.com/neondatabase/add-mcp) |
|
|
53
57
|
|
|
54
58
|
## Commands
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare function install(args: string[], cwd: string): Promise<void>;
|
|
2
|
-
export declare function wireSkills(
|
|
2
|
+
export declare function wireSkills(cwd: string): Promise<void>;
|
package/dist/commands/install.js
CHANGED
|
@@ -1,23 +1,13 @@
|
|
|
1
1
|
import { npm, npx, log } from '../utils/index.js';
|
|
2
2
|
import { scanNodeModules, collectMcpServers } from '../scanner/index.js';
|
|
3
|
-
import {
|
|
4
|
-
import { promisify } from 'node:util';
|
|
5
|
-
import { dirname } from 'node:path';
|
|
6
|
-
import { homedir } from 'node:os';
|
|
7
|
-
const execFileAsync = promisify(execFile);
|
|
8
|
-
function isGlobalFlag(args) {
|
|
9
|
-
return args.includes('-g') || args.includes('--global');
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Resolve the node_modules root to scan. For global installs, uses `npm root -g`.
|
|
13
|
-
*/
|
|
14
|
-
async function resolveNodeModulesRoot(args, cwd) {
|
|
15
|
-
if (!isGlobalFlag(args))
|
|
16
|
-
return cwd;
|
|
17
|
-
const { stdout } = await execFileAsync('npm', ['root', '-g']);
|
|
18
|
-
return dirname(stdout.trim());
|
|
19
|
-
}
|
|
3
|
+
import { copyConfigs } from '../configs/index.js';
|
|
20
4
|
export async function install(args, cwd) {
|
|
5
|
+
// Reject global installs — skillpm is workspace-only
|
|
6
|
+
if (args.includes('-g') || args.includes('--global')) {
|
|
7
|
+
log.error('Global installs are not supported. skillpm works per-workspace with package.json and lockfiles.');
|
|
8
|
+
log.error('For global skills, use: npx skills add <path>');
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
21
11
|
// Step 1: npm install
|
|
22
12
|
const npmArgs = ['install', ...args];
|
|
23
13
|
log.info(`Running npm ${npmArgs.join(' ')}`);
|
|
@@ -34,15 +24,11 @@ export async function install(args, cwd) {
|
|
|
34
24
|
process.exit(1);
|
|
35
25
|
}
|
|
36
26
|
// Step 2: Scan for skills and wire them
|
|
37
|
-
|
|
38
|
-
// For global installs, wire skills into user's home directory (not the npm prefix)
|
|
39
|
-
const wireTarget = isGlobalFlag(args) ? homedir() : cwd;
|
|
40
|
-
await wireSkills(scanRoot, wireTarget);
|
|
27
|
+
await wireSkills(cwd);
|
|
41
28
|
}
|
|
42
|
-
export async function wireSkills(
|
|
43
|
-
const wireCwd = wireTarget ?? scanRoot;
|
|
29
|
+
export async function wireSkills(cwd) {
|
|
44
30
|
// Scan node_modules/ for SKILL.md packages
|
|
45
|
-
const skills = await scanNodeModules(
|
|
31
|
+
const skills = await scanNodeModules(cwd);
|
|
46
32
|
if (skills.length === 0) {
|
|
47
33
|
log.info('No skill packages found in node_modules/');
|
|
48
34
|
return;
|
|
@@ -52,7 +38,7 @@ export async function wireSkills(scanRoot, wireTarget) {
|
|
|
52
38
|
for (const skill of skills) {
|
|
53
39
|
log.info(`Linking ${log.skill(skill.name, skill.version)} into agent directories`);
|
|
54
40
|
try {
|
|
55
|
-
await npx(['skills', 'add', skill.skillDir, '--all', '-y'], { cwd
|
|
41
|
+
await npx(['skills', 'add', skill.skillDir, '--all', '-y'], { cwd });
|
|
56
42
|
log.success(`Linked ${skill.name}`);
|
|
57
43
|
}
|
|
58
44
|
catch (err) {
|
|
@@ -70,7 +56,7 @@ export async function wireSkills(scanRoot, wireTarget) {
|
|
|
70
56
|
for (const server of mcpServers) {
|
|
71
57
|
log.info(`Configuring MCP server: ${server}`);
|
|
72
58
|
try {
|
|
73
|
-
await npx(['add-mcp', server, '-y'], { cwd
|
|
59
|
+
await npx(['add-mcp', server, '-y'], { cwd });
|
|
74
60
|
log.success(`Configured ${server}`);
|
|
75
61
|
}
|
|
76
62
|
catch (err) {
|
|
@@ -79,31 +65,17 @@ export async function wireSkills(scanRoot, wireTarget) {
|
|
|
79
65
|
}
|
|
80
66
|
}
|
|
81
67
|
}
|
|
82
|
-
//
|
|
83
|
-
for (const skill of skills) {
|
|
84
|
-
for (const agentFile of skill.agents) {
|
|
85
|
-
log.info(`Wiring agent from ${log.skill(skill.name, skill.version)}`);
|
|
86
|
-
try {
|
|
87
|
-
await npx(['add-agent', agentFile, '--package', skill.name], { cwd: wireCwd });
|
|
88
|
-
log.success(`Wired agent ${agentFile}`);
|
|
89
|
-
}
|
|
90
|
-
catch (err) {
|
|
91
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
92
|
-
log.warn(`Failed to wire agent: ${msg}`);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
// Wire prompts/instructions via add-prompt
|
|
68
|
+
// Copy configs/ files (agents, prompts, rules) into workspace
|
|
97
69
|
for (const skill of skills) {
|
|
98
|
-
|
|
99
|
-
log.info(`
|
|
70
|
+
if (skill.configsDir) {
|
|
71
|
+
log.info(`Copying config files from ${log.skill(skill.name, skill.version)}`);
|
|
100
72
|
try {
|
|
101
|
-
await
|
|
102
|
-
log.success(`
|
|
73
|
+
const copied = await copyConfigs(skill.configsDir, cwd, skill.name, skill.configPrefix);
|
|
74
|
+
log.success(`Copied ${copied.length} config file(s) from ${skill.name}`);
|
|
103
75
|
}
|
|
104
76
|
catch (err) {
|
|
105
77
|
const msg = err instanceof Error ? err.message : String(err);
|
|
106
|
-
log.warn(`Failed to
|
|
78
|
+
log.warn(`Failed to copy config files from ${skill.name}: ${msg}`);
|
|
107
79
|
}
|
|
108
80
|
}
|
|
109
81
|
}
|
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
import { npm,
|
|
1
|
+
import { npm, log } from '../utils/index.js';
|
|
2
2
|
import { wireSkills } from './install.js';
|
|
3
|
+
import { removeConfigs } from '../configs/index.js';
|
|
3
4
|
export async function uninstall(args, cwd) {
|
|
4
5
|
if (args.length === 0) {
|
|
5
6
|
log.error('Usage: skillpm uninstall <skill> [skill...]');
|
|
6
7
|
process.exit(1);
|
|
7
8
|
}
|
|
8
|
-
// Clean up
|
|
9
|
+
// Clean up wired files before npm uninstall
|
|
9
10
|
for (const pkg of args) {
|
|
10
11
|
try {
|
|
11
|
-
await
|
|
12
|
+
const removed = await removeConfigs(cwd, pkg);
|
|
13
|
+
if (removed.length > 0) {
|
|
14
|
+
log.info(`Removed ${removed.length} config file(s) from ${pkg}`);
|
|
15
|
+
}
|
|
12
16
|
}
|
|
13
17
|
catch {
|
|
14
|
-
// Ignore — package may not have had
|
|
15
|
-
}
|
|
16
|
-
try {
|
|
17
|
-
await npx(['add-prompt', '--remove-package', pkg], { cwd });
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
// Ignore — package may not have had prompts
|
|
18
|
+
// Ignore — package may not have had configs
|
|
21
19
|
}
|
|
22
20
|
}
|
|
23
21
|
log.info(`Running npm uninstall ${args.join(' ')}`);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copy all files from a skill's configs/ directory to the workspace,
|
|
3
|
+
* auto-prefixing filenames to avoid conflicts between installed skills.
|
|
4
|
+
*
|
|
5
|
+
* The prefix used is, in priority order:
|
|
6
|
+
* 1. `configPrefix` argument (from skillpm.configPrefix in package.json)
|
|
7
|
+
* 2. De-scoped package name (strips "@scope/" from scoped packages)
|
|
8
|
+
*
|
|
9
|
+
* Examples:
|
|
10
|
+
* packageName="@mcaps/spt-iq-consumption", configPrefix="consumption"
|
|
11
|
+
* → "consumption-briefing.md"
|
|
12
|
+
* packageName="@mcaps/spt-iq-consumption", no configPrefix
|
|
13
|
+
* → "spt-iq-consumption-briefing.md"
|
|
14
|
+
* packageName="my-skill", no configPrefix
|
|
15
|
+
* → "my-skill-briefing.md"
|
|
16
|
+
*/
|
|
17
|
+
export declare function copyConfigs(configsDir: string, cwd: string, packageName: string, configPrefix?: string): Promise<string[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Remove all config files for a package using the manifest.
|
|
20
|
+
*/
|
|
21
|
+
export declare function removeConfigs(cwd: string, packageName: string): Promise<string[]>;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { readdir, copyFile, mkdir, unlink, readFile, writeFile, stat } from 'node:fs/promises';
|
|
2
|
+
import { join, relative, dirname, basename } from 'node:path';
|
|
3
|
+
const MANIFEST_DIR = '.skillpm';
|
|
4
|
+
const MANIFEST_FILE = 'manifest.json';
|
|
5
|
+
/** Normalize path separators to forward slashes for cross-platform consistency. */
|
|
6
|
+
function normalizePath(p) {
|
|
7
|
+
return p.replace(/\\/g, '/');
|
|
8
|
+
}
|
|
9
|
+
async function readManifest(cwd) {
|
|
10
|
+
try {
|
|
11
|
+
const raw = await readFile(join(cwd, MANIFEST_DIR, MANIFEST_FILE), 'utf-8');
|
|
12
|
+
return JSON.parse(raw);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async function writeManifest(cwd, manifest) {
|
|
19
|
+
const dir = join(cwd, MANIFEST_DIR);
|
|
20
|
+
await mkdir(dir, { recursive: true });
|
|
21
|
+
await writeFile(join(dir, MANIFEST_FILE), JSON.stringify(manifest, null, 2) + '\n');
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Recursively collect all files in a directory, returning paths relative to the root.
|
|
25
|
+
*/
|
|
26
|
+
async function walkDir(dir, root) {
|
|
27
|
+
root ??= dir;
|
|
28
|
+
const files = [];
|
|
29
|
+
let entries;
|
|
30
|
+
try {
|
|
31
|
+
entries = await readdir(dir);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return files;
|
|
35
|
+
}
|
|
36
|
+
for (const name of entries) {
|
|
37
|
+
const full = join(dir, name);
|
|
38
|
+
const s = await stat(full);
|
|
39
|
+
if (s.isDirectory()) {
|
|
40
|
+
files.push(...(await walkDir(full, root)));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
files.push(normalizePath(relative(root, full)));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return files;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Strip npm scope from a package name.
|
|
50
|
+
* e.g. "@mcaps/spt-iq-consumption" → "spt-iq-consumption"
|
|
51
|
+
* "spt-iq-consumption" → "spt-iq-consumption"
|
|
52
|
+
*/
|
|
53
|
+
function stripScope(packageName) {
|
|
54
|
+
if (packageName.startsWith('@')) {
|
|
55
|
+
const slash = packageName.indexOf('/');
|
|
56
|
+
return slash >= 0 ? packageName.slice(slash + 1) : packageName;
|
|
57
|
+
}
|
|
58
|
+
return packageName;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Auto-prefix a filename with the resolved prefix to avoid conflicts.
|
|
62
|
+
* e.g. "reviewer.md" with prefix "my-skill" → "my-skill-reviewer.md"
|
|
63
|
+
*/
|
|
64
|
+
function prefixFilename(relPath, prefix) {
|
|
65
|
+
const dir = dirname(relPath);
|
|
66
|
+
const file = basename(relPath);
|
|
67
|
+
const prefixed = `${prefix}-${file}`;
|
|
68
|
+
return normalizePath(dir === '.' ? prefixed : join(dir, prefixed));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Copy all files from a skill's configs/ directory to the workspace,
|
|
72
|
+
* auto-prefixing filenames to avoid conflicts between installed skills.
|
|
73
|
+
*
|
|
74
|
+
* The prefix used is, in priority order:
|
|
75
|
+
* 1. `configPrefix` argument (from skillpm.configPrefix in package.json)
|
|
76
|
+
* 2. De-scoped package name (strips "@scope/" from scoped packages)
|
|
77
|
+
*
|
|
78
|
+
* Examples:
|
|
79
|
+
* packageName="@mcaps/spt-iq-consumption", configPrefix="consumption"
|
|
80
|
+
* → "consumption-briefing.md"
|
|
81
|
+
* packageName="@mcaps/spt-iq-consumption", no configPrefix
|
|
82
|
+
* → "spt-iq-consumption-briefing.md"
|
|
83
|
+
* packageName="my-skill", no configPrefix
|
|
84
|
+
* → "my-skill-briefing.md"
|
|
85
|
+
*/
|
|
86
|
+
export async function copyConfigs(configsDir, cwd, packageName, configPrefix) {
|
|
87
|
+
const prefix = configPrefix ?? stripScope(packageName);
|
|
88
|
+
const files = await walkDir(configsDir);
|
|
89
|
+
const copied = [];
|
|
90
|
+
for (const relPath of files) {
|
|
91
|
+
const prefixed = prefixFilename(relPath, prefix);
|
|
92
|
+
const src = join(configsDir, relPath);
|
|
93
|
+
const dest = join(cwd, prefixed);
|
|
94
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
95
|
+
await copyFile(src, dest);
|
|
96
|
+
copied.push(prefixed);
|
|
97
|
+
}
|
|
98
|
+
// Update manifest
|
|
99
|
+
const manifest = await readManifest(cwd);
|
|
100
|
+
manifest[packageName] = copied;
|
|
101
|
+
await writeManifest(cwd, manifest);
|
|
102
|
+
return copied;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Remove all config files for a package using the manifest.
|
|
106
|
+
*/
|
|
107
|
+
export async function removeConfigs(cwd, packageName) {
|
|
108
|
+
const manifest = await readManifest(cwd);
|
|
109
|
+
const files = manifest[packageName];
|
|
110
|
+
if (!files || files.length === 0)
|
|
111
|
+
return [];
|
|
112
|
+
const removed = [];
|
|
113
|
+
for (const relPath of files) {
|
|
114
|
+
try {
|
|
115
|
+
await unlink(join(cwd, relPath));
|
|
116
|
+
removed.push(relPath);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// File already gone
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
delete manifest[packageName];
|
|
123
|
+
await writeManifest(cwd, manifest);
|
|
124
|
+
return removed;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export declare const SkillpmFieldSchema: z.ZodOptional<z.ZodObject<{
|
|
3
3
|
mcpServers: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
4
|
+
configPrefix: z.ZodOptional<z.ZodString>;
|
|
4
5
|
}, z.core.$strict>>;
|
|
5
6
|
export type SkillpmField = z.infer<typeof SkillpmFieldSchema>;
|
|
6
7
|
export interface SkillPackageJson {
|
|
@@ -19,8 +20,13 @@ export interface SkillInfo {
|
|
|
19
20
|
mcpServers: string[];
|
|
20
21
|
/** True if SKILL.md is at package root instead of skills/<name>/ */
|
|
21
22
|
legacy?: boolean;
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
|
|
23
|
+
/** Path to configs/ directory if present (mirrors workspace layout) */
|
|
24
|
+
configsDir?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Optional prefix override for config file naming.
|
|
27
|
+
* When set, used instead of the (de-scoped) package name.
|
|
28
|
+
* e.g. configPrefix: "consumption" → "consumption--briefing.md"
|
|
29
|
+
* Declared via skillpm.configPrefix in package.json.
|
|
30
|
+
*/
|
|
31
|
+
configPrefix?: string;
|
|
26
32
|
}
|
package/dist/manifest/schema.js
CHANGED
package/dist/scanner/index.js
CHANGED
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
import { readdir, access } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { readPackageJson, parseSkillpmField } from '../manifest/index.js';
|
|
4
|
-
/**
|
|
5
|
-
* Scan a directory for .md files (used for agents/ and prompts/ dirs).
|
|
6
|
-
*/
|
|
7
|
-
async function scanMdFiles(dir) {
|
|
8
|
-
let entries;
|
|
9
|
-
try {
|
|
10
|
-
entries = await readdir(dir);
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
return [];
|
|
14
|
-
}
|
|
15
|
-
return entries.filter((e) => e.endsWith('.md')).map((e) => join(dir, e));
|
|
16
|
-
}
|
|
17
4
|
/**
|
|
18
5
|
* Scan node_modules/ for packages that contain a skills/<name>/SKILL.md file.
|
|
19
6
|
* Returns metadata for each discovered skill package.
|
|
@@ -57,10 +44,22 @@ export async function scanNodeModules(cwd) {
|
|
|
57
44
|
}
|
|
58
45
|
return skills;
|
|
59
46
|
}
|
|
47
|
+
async function hasDir(dir) {
|
|
48
|
+
try {
|
|
49
|
+
await access(dir);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
60
56
|
async function tryReadSkill(pkgDir) {
|
|
61
57
|
const pkg = await readPackageJson(pkgDir);
|
|
62
58
|
if (!pkg)
|
|
63
59
|
return null;
|
|
60
|
+
// Check for configs/ directory
|
|
61
|
+
const configsDir = join(pkgDir, 'configs');
|
|
62
|
+
const hasConfigs = await hasDir(configsDir);
|
|
64
63
|
// Preferred: look for skills/*/SKILL.md
|
|
65
64
|
const skillsDir = join(pkgDir, 'skills');
|
|
66
65
|
let skillSubdirs;
|
|
@@ -79,16 +78,14 @@ async function tryReadSkill(pkgDir) {
|
|
|
79
78
|
continue;
|
|
80
79
|
}
|
|
81
80
|
const skillpm = parseSkillpmField(pkg);
|
|
82
|
-
const agents = await scanMdFiles(join(pkgDir, 'agents'));
|
|
83
|
-
const prompts = await scanMdFiles(join(pkgDir, 'prompts'));
|
|
84
81
|
return {
|
|
85
82
|
name: pkg.name,
|
|
86
83
|
version: pkg.version,
|
|
87
84
|
path: pkgDir,
|
|
88
85
|
skillDir,
|
|
89
86
|
mcpServers: skillpm?.mcpServers ?? [],
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
configsDir: hasConfigs ? configsDir : undefined,
|
|
88
|
+
configPrefix: skillpm?.configPrefix,
|
|
92
89
|
};
|
|
93
90
|
}
|
|
94
91
|
// Fallback: root SKILL.md (legacy format)
|
|
@@ -99,8 +96,6 @@ async function tryReadSkill(pkgDir) {
|
|
|
99
96
|
return null;
|
|
100
97
|
}
|
|
101
98
|
const skillpm = parseSkillpmField(pkg);
|
|
102
|
-
const agents = await scanMdFiles(join(pkgDir, 'agents'));
|
|
103
|
-
const prompts = await scanMdFiles(join(pkgDir, 'prompts'));
|
|
104
99
|
return {
|
|
105
100
|
name: pkg.name,
|
|
106
101
|
version: pkg.version,
|
|
@@ -108,8 +103,8 @@ async function tryReadSkill(pkgDir) {
|
|
|
108
103
|
skillDir: pkgDir,
|
|
109
104
|
mcpServers: skillpm?.mcpServers ?? [],
|
|
110
105
|
legacy: true,
|
|
111
|
-
|
|
112
|
-
|
|
106
|
+
configsDir: hasConfigs ? configsDir : undefined,
|
|
107
|
+
configPrefix: skillpm?.configPrefix,
|
|
113
108
|
};
|
|
114
109
|
}
|
|
115
110
|
/**
|